下面列出了org.objectweb.asm.Type#SHORT_TYPE 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
public static Number rebox(Number cst, Type t) {
if(t == Type.BYTE_TYPE) {
return cst.byteValue();
} else if(t == Type.SHORT_TYPE) {
return cst.shortValue();
} else if(t == Type.INT_TYPE) {
return cst.intValue();
} else if(t == Type.LONG_TYPE) {
return cst.longValue();
} else if(t == Type.FLOAT_TYPE) {
return cst.floatValue();
} else if(t == Type.DOUBLE_TYPE) {
return cst.doubleValue();
} else {
throw new UnsupportedOperationException(String.format("%s (%s) to %s", cst, cst.getClass(), t));
}
}
public static Type getUnboxedType(Type type) {
if (Constants.TYPE_INTEGER.equals(type)) {
return Type.INT_TYPE;
} else if (Constants.TYPE_BOOLEAN.equals(type)) {
return Type.BOOLEAN_TYPE;
} else if (Constants.TYPE_DOUBLE.equals(type)) {
return Type.DOUBLE_TYPE;
} else if (Constants.TYPE_LONG.equals(type)) {
return Type.LONG_TYPE;
} else if (Constants.TYPE_CHARACTER.equals(type)) {
return Type.CHAR_TYPE;
} else if (Constants.TYPE_BYTE.equals(type)) {
return Type.BYTE_TYPE;
} else if (Constants.TYPE_FLOAT.equals(type)) {
return Type.FLOAT_TYPE;
} else if (Constants.TYPE_SHORT.equals(type)) {
return Type.SHORT_TYPE;
} else {
return type;
}
}
@VisibleForTesting
static Type getType(String type) {
if (type.equals(Void.TYPE.getName())) {
return Type.VOID_TYPE;
} else if (type.equals(Boolean.TYPE.getName())) {
return Type.BOOLEAN_TYPE;
} else if (type.equals(Character.TYPE.getName())) {
return Type.CHAR_TYPE;
} else if (type.equals(Byte.TYPE.getName())) {
return Type.BYTE_TYPE;
} else if (type.equals(Short.TYPE.getName())) {
return Type.SHORT_TYPE;
} else if (type.equals(Integer.TYPE.getName())) {
return Type.INT_TYPE;
} else if (type.equals(Float.TYPE.getName())) {
return Type.FLOAT_TYPE;
} else if (type.equals(Long.TYPE.getName())) {
return Type.LONG_TYPE;
} else if (type.equals(Double.TYPE.getName())) {
return Type.DOUBLE_TYPE;
} else if (type.endsWith("[]")) {
return getArrayType(type);
} else {
return Type.getObjectType(type.replace('.', '/'));
}
}
Type getArrayElementType(int type) {
switch (type) {
case T_BOOLEAN:
return Type.BOOLEAN_TYPE;
case T_BYTE:
return Type.BYTE_TYPE;
case T_CHAR:
return Type.CHAR_TYPE;
case T_DOUBLE:
return Type.DOUBLE_TYPE;
case T_FLOAT:
return Type.FLOAT_TYPE;
case T_INT:
return Type.INT_TYPE;
case T_LONG:
return Type.LONG_TYPE;
case T_SHORT:
return Type.SHORT_TYPE;
}
throw new BuildStackFrameException("Illegal array type code: " + type);
}
public static Type getCastType(int opcode) {
switch (opcode) {
case I2B:
return Type.BYTE_TYPE;
case I2C:
return Type.CHAR_TYPE;
case I2S:
return Type.SHORT_TYPE;
case L2I:
case F2I:
case D2I:
return Type.INT_TYPE;
case I2L:
case F2L:
case D2L:
return Type.LONG_TYPE;
case I2F:
case L2F:
case D2F:
return Type.FLOAT_TYPE;
case I2D:
case L2D:
case F2D:
return Type.DOUBLE_TYPE;
default:
throw new IllegalArgumentException(Printer.OPCODES[opcode]);
}
}
public static int getNegateOpcode(Type type) {
if (type == Type.INT_TYPE || type == Type.SHORT_TYPE || type == Type.BYTE_TYPE) {
return Opcodes.INEG;
} else if (type == Type.LONG_TYPE) {
return Opcodes.LNEG;
} else if (type == Type.FLOAT_TYPE) {
return Opcodes.FNEG;
} else if (type == Type.DOUBLE_TYPE) {
return Opcodes.DNEG;
} else {
throw new IllegalArgumentException(type.toString());
}
}
/**
* @param arg
* Operand value of a NEWARRAY instruction.
*
* @return Array element type.
*/
public static Type newArrayArgToType(int arg) {
switch(arg) {
case 4: return Type.BOOLEAN_TYPE;
case 5: return Type.CHAR_TYPE;
case 6: return Type.FLOAT_TYPE;
case 7: return Type.DOUBLE_TYPE;
case 8: return Type.BYTE_TYPE;
case 9: return Type.SHORT_TYPE;
case 10: return Type.INT_TYPE;
case 11: return Type.LONG_TYPE;
default: break;
}
throw new IllegalArgumentException("Unexpected NEWARRAY arg: " + arg);
}
/**
* @param opcode
* @return
*/
private static Type toType ( int opcode ) {
switch ( opcode ) {
case Opcodes.LLOAD:
return Type.LONG_TYPE;
case Opcodes.ILOAD:
return Type.INT_TYPE;
case Opcodes.FLOAD:
return Type.FLOAT_TYPE;
case Opcodes.DLOAD:
return Type.DOUBLE_TYPE;
case Opcodes.ALOAD:
return Type.getType("Ljava/lang/Object;"); //$NON-NLS-1$
case Opcodes.IALOAD:
return Type.INT_TYPE;
case Opcodes.LALOAD:
return Type.LONG_TYPE;
case Opcodes.FALOAD:
return Type.FLOAT_TYPE;
case Opcodes.DALOAD:
return Type.DOUBLE_TYPE;
case Opcodes.BALOAD:
return Type.BYTE_TYPE;
case Opcodes.CALOAD:
return Type.CHAR_TYPE;
case Opcodes.SALOAD:
return Type.SHORT_TYPE;
}
return Type.VOID_TYPE;
}
/**
* Generates the instruction to cast from the first given type to the other.
*
* @param methodVisitor the method visitor to use to generate the instruction.
* @param from a Type.
* @param to a Type.
*/
static void cast(final MethodVisitor methodVisitor, final Type from, final Type to) {
if (from != to) {
if (from == Type.DOUBLE_TYPE) {
if (to == Type.FLOAT_TYPE) {
methodVisitor.visitInsn(Opcodes.D2F);
} else if (to == Type.LONG_TYPE) {
methodVisitor.visitInsn(Opcodes.D2L);
} else {
methodVisitor.visitInsn(Opcodes.D2I);
cast(methodVisitor, Type.INT_TYPE, to);
}
} else if (from == Type.FLOAT_TYPE) {
if (to == Type.DOUBLE_TYPE) {
methodVisitor.visitInsn(Opcodes.F2D);
} else if (to == Type.LONG_TYPE) {
methodVisitor.visitInsn(Opcodes.F2L);
} else {
methodVisitor.visitInsn(Opcodes.F2I);
cast(methodVisitor, Type.INT_TYPE, to);
}
} else if (from == Type.LONG_TYPE) {
if (to == Type.DOUBLE_TYPE) {
methodVisitor.visitInsn(Opcodes.L2D);
} else if (to == Type.FLOAT_TYPE) {
methodVisitor.visitInsn(Opcodes.L2F);
} else {
methodVisitor.visitInsn(Opcodes.L2I);
cast(methodVisitor, Type.INT_TYPE, to);
}
} else {
if (to == Type.BYTE_TYPE) {
methodVisitor.visitInsn(Opcodes.I2B);
} else if (to == Type.CHAR_TYPE) {
methodVisitor.visitInsn(Opcodes.I2C);
} else if (to == Type.DOUBLE_TYPE) {
methodVisitor.visitInsn(Opcodes.I2D);
} else if (to == Type.FLOAT_TYPE) {
methodVisitor.visitInsn(Opcodes.I2F);
} else if (to == Type.LONG_TYPE) {
methodVisitor.visitInsn(Opcodes.I2L);
} else if (to == Type.SHORT_TYPE) {
methodVisitor.visitInsn(Opcodes.I2S);
}
}
}
}
public static Type computeType(Object cst) {
if (cst == null) {
return Type.getType("Ljava/lang/Object;");
} else if (cst instanceof Integer) {
int val = ((Integer) cst).intValue();
if (val >= Byte.MIN_VALUE && val <= Byte.MAX_VALUE) {
return Type.BYTE_TYPE;
} else if (val >= Short.MIN_VALUE && val <= Short.MAX_VALUE) {
return Type.SHORT_TYPE;
} else {
return Type.INT_TYPE;
}
// return Type.INT_TYPE;
} else if (cst instanceof Long) {
return Type.LONG_TYPE;
} else if (cst instanceof Float) {
return Type.FLOAT_TYPE;
} else if (cst instanceof Double) {
return Type.DOUBLE_TYPE;
} else if (cst instanceof String) {
return Type.getType("Ljava/lang/String;");
} else if (cst instanceof Type) {
Type type = (Type) cst;
if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) {
return Type.getType("Ljava/lang/Class;");
} else if (type.getSort() == Type.METHOD) {
return Type.getType("Ljava/lang/invoke/MethodType;");
} else {
throw new RuntimeException("Invalid type: " + cst);
}
} else if (cst instanceof Handle) {
return Type.getType("Ljava/lang/invoke/MethodHandle;");
} else if (cst instanceof Boolean) {
return Type.BOOLEAN_TYPE;
} else if(cst instanceof Byte) {
return Type.BYTE_TYPE;
} else if (cst instanceof Character) {
return Type.CHAR_TYPE;
} else if(cst instanceof Short) {
return Type.SHORT_TYPE;
} else {
throw new RuntimeException("Invalid type: " + cst);
}
}
public static InsnValue shortValue(Object cst) {
return new InsnValue(Type.SHORT_TYPE, cst);
}
private void callTheDecoder(MethodVisitor methodVisitor, Type type) {
if (type == Type.BYTE_TYPE) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOneByte", "()B", false);
} else if (type == Type.BOOLEAN_TYPE) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOneBoolean", "()Z", false);
} else if (type == Type.CHAR_TYPE) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOneCharacter", "()C", false);
} else if (type == Type.SHORT_TYPE) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOneShort", "()S", false);
} else if (type == Type.INT_TYPE) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOneInteger", "()I", false);
} else if (type == Type.LONG_TYPE) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOneLong", "()J", false);
} else if (type == Type.FLOAT_TYPE) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOneFloat", "()F", false);
} else if (type == Type.DOUBLE_TYPE) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOneDouble", "()D", false);
} else if (isArrayOfTypeAndDimensions(type, Type.BYTE_TYPE, 1)) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOneByteArray", "()[B", false);
} else if (isArrayOfTypeAndDimensions(type, Type.BOOLEAN_TYPE, 1)) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOneBooleanArray", "()[Z", false);
} else if (isArrayOfTypeAndDimensions(type, Type.CHAR_TYPE, 1)) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOneCharacterArray", "()[C", false);
} else if (isArrayOfTypeAndDimensions(type, Type.SHORT_TYPE, 1)) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOneShortArray", "()[S", false);
} else if (isArrayOfTypeAndDimensions(type, Type.INT_TYPE, 1)) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOneIntegerArray", "()[I", false);
} else if (isArrayOfTypeAndDimensions(type, Type.LONG_TYPE, 1)) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOneLongArray", "()[J", false);
} else if (isArrayOfTypeAndDimensions(type, Type.FLOAT_TYPE, 1)) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOneFloatArray", "()[F", false);
} else if (isArrayOfTypeAndDimensions(type, Type.DOUBLE_TYPE, 1)) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOneDoubleArray", "()[D", false);
} else if (isString(type)) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOneString", "()Ljava/lang/String;", false);
} else if (isAddress(type)) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOneAddress", "()Lavm/Address;", false);
} else if(isBigInteger(type)) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOneBigInteger", "()Ljava/math/BigInteger;", false);
} else if (isArrayOfTypeAndDimensions(type, Type.BYTE_TYPE, 2)) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOne2DByteArray", "()[[B", false);
} else if (isArrayOfTypeAndDimensions(type, Type.BOOLEAN_TYPE, 2)) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOne2DBooleanArray", "()[[Z", false);
} else if (isArrayOfTypeAndDimensions(type, Type.CHAR_TYPE, 2)) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOne2DCharacterArray", "()[[C", false);
} else if (isArrayOfTypeAndDimensions(type, Type.SHORT_TYPE, 2)) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOne2DShortArray", "()[[S", false);
} else if (isArrayOfTypeAndDimensions(type, Type.INT_TYPE, 2)) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOne2DIntegerArray", "()[[I", false);
} else if (isArrayOfTypeAndDimensions(type, Type.LONG_TYPE, 2)) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOne2DLongArray", "()[[J", false);
} else if (isArrayOfTypeAndDimensions(type, Type.FLOAT_TYPE, 2)) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOne2DFloatArray", "()[[F", false);
} else if (isArrayOfTypeAndDimensions(type, Type.DOUBLE_TYPE, 2)) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOne2DDoubleArray", "()[[D", false);
} else if (type.getSort() == Type.ARRAY && type.getDimensions() == 1 && isString(type.getElementType())) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOneStringArray", "()[Ljava/lang/String;", false);
} else if (type.getSort() == Type.ARRAY && type.getDimensions() == 1 && isAddress(type.getElementType())) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOneAddressArray", "()[Lavm/Address;", false);
} else if(type.getSort() == Type.ARRAY && type.getDimensions() == 1 && isBigInteger(type.getElementType())) {
methodVisitor.visitMethodInsn(INVOKEVIRTUAL, "org/aion/avm/userlib/abi/ABIDecoder", "decodeOneBigIntegerArray", "()[Ljava/math/BigInteger;", false);
} else {
throw new ABICompilerException("Need to decode an unsupported ABI type");
}
}
public AbstractValue binaryOperation(AbstractInsnNode insnNode, AbstractValue symbolicValue1, AbstractValue symbolicValue2) throws AnalyzerException {
symbolicValue1.addUsage(insnNode);
symbolicValue2.addUsage(insnNode);
switch (insnNode.getOpcode()) {
case IALOAD:
return intSymbolicValue(insnNode);
case LALOAD:
return longSymbolicValue(insnNode);
case FALOAD:
return floatSymbolicValue(insnNode);
case DALOAD:
return doubleSymbolicValue(insnNode);
case AALOAD: {
Type arrayType = symbolicValue1.getType();
if (arrayType == null)
return new UnknownValue(insnNode, null);
if (arrayType.getSort() != Type.ARRAY)
throw new AnalyzerException(insnNode, symbolicValue1.toString() + " is not array");
return new UnknownValue(insnNode, arrayType.getElementType());
}
case BALOAD:
return new UnknownValue(insnNode, Type.BYTE_TYPE);
case CALOAD:
return new UnknownValue(insnNode, Type.CHAR_TYPE);
case SALOAD:
return new UnknownValue(insnNode, Type.SHORT_TYPE);
case IADD:
case ISUB:
case IMUL:
case IDIV:
case IREM:
case ISHL:
case ISHR:
case IUSHR:
case IAND:
case IOR:
case IXOR:
case LCMP:
case FCMPL:
case FCMPG:
case DCMPL:
case DCMPG:
return intSymbolicValue(insnNode);
case LADD:
case LSUB:
case LMUL:
case LDIV:
case LREM:
case LSHL:
case LSHR:
case LUSHR:
case LAND:
case LOR:
case LXOR:
return longSymbolicValue(insnNode);
case FADD:
case FSUB:
case FMUL:
case FDIV:
case FREM:
return floatSymbolicValue(insnNode);
case DADD:
case DSUB:
case DMUL:
case DDIV:
case DREM:
return doubleSymbolicValue(insnNode);
case IF_ICMPEQ:
case IF_ICMPNE:
case IF_ICMPLT:
case IF_ICMPGE:
case IF_ICMPGT:
case IF_ICMPLE:
case IF_ACMPEQ:
case IF_ACMPNE:
case PUTFIELD:
return null;
default:
throw new IllegalArgumentException("Invalid instruction opcode.");
}
}
public void cast(final Type from, final Type to) {
if (from != to) {
if (from == Type.DOUBLE_TYPE) {
if (to == Type.FLOAT_TYPE) {
mv.visitInsn(Opcodes.D2F);
} else if (to == Type.LONG_TYPE) {
mv.visitInsn(Opcodes.D2L);
} else {
mv.visitInsn(Opcodes.D2I);
cast(Type.INT_TYPE, to);
}
} else if (from == Type.FLOAT_TYPE) {
if (to == Type.DOUBLE_TYPE) {
mv.visitInsn(Opcodes.F2D);
} else if (to == Type.LONG_TYPE) {
mv.visitInsn(Opcodes.F2L);
} else {
mv.visitInsn(Opcodes.F2I);
cast(Type.INT_TYPE, to);
}
} else if (from == Type.LONG_TYPE) {
if (to == Type.DOUBLE_TYPE) {
mv.visitInsn(Opcodes.L2D);
} else if (to == Type.FLOAT_TYPE) {
mv.visitInsn(Opcodes.L2F);
} else {
mv.visitInsn(Opcodes.L2I);
cast(Type.INT_TYPE, to);
}
} else {
if (to == Type.BYTE_TYPE) {
mv.visitInsn(Opcodes.I2B);
} else if (to == Type.CHAR_TYPE) {
mv.visitInsn(Opcodes.I2C);
} else if (to == Type.DOUBLE_TYPE) {
mv.visitInsn(Opcodes.I2D);
} else if (to == Type.FLOAT_TYPE) {
mv.visitInsn(Opcodes.I2F);
} else if (to == Type.LONG_TYPE) {
mv.visitInsn(Opcodes.I2L);
} else if (to == Type.SHORT_TYPE) {
mv.visitInsn(Opcodes.I2S);
}
}
}
}
void pushStack(StackInfo info) {
super.visitIntInsn(SIPUSH, info.stackSize());
super.visitTypeInsn(ANEWARRAY, "java/lang/Object");
for (int i = info.stackSize() - 1; i >= 0; --i) {
Type t = info.getStack(i);
if (t != null) {
if (t == Type.BOOLEAN_TYPE || t == Type.BYTE_TYPE || t == Type.SHORT_TYPE || t == Type.INT_TYPE || t == Type.CHAR_TYPE) {
super.visitInsn(DUP_X1);
super.visitInsn(SWAP);
super.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
super.visitIntInsn(SIPUSH, i);
super.visitInsn(SWAP);
} else if (t == Type.FLOAT_TYPE) {
super.visitInsn(DUP_X1);
super.visitInsn(SWAP);
super.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false);
super.visitIntInsn(SIPUSH, i);
super.visitInsn(SWAP);
} else if (t == Type.LONG_TYPE) {
super.visitInsn(DUP_X2);
super.visitInsn(DUP_X2);
super.visitInsn(POP);
super.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false);
super.visitIntInsn(SIPUSH, i);
super.visitInsn(SWAP);
} else if (t == Type.DOUBLE_TYPE) {
super.visitInsn(DUP_X2);
super.visitInsn(DUP_X2);
super.visitInsn(POP);
super.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false);
super.visitIntInsn(SIPUSH, i);
super.visitInsn(SWAP);
} else {
super.visitInsn(DUP_X1);
super.visitInsn(SWAP);
super.visitIntInsn(SIPUSH, i);
super.visitInsn(SWAP);
}
super.visitInsn(AASTORE);
}
}
}
/**
* Generates the instruction to cast from the first given type to the other.
*
* @param from a Type.
* @param to a Type.
*/
public void cast(final Type from, final Type to) {
if (from != to) {
if (from == Type.DOUBLE_TYPE) {
if (to == Type.FLOAT_TYPE) {
mv.visitInsn(Opcodes.D2F);
} else if (to == Type.LONG_TYPE) {
mv.visitInsn(Opcodes.D2L);
} else {
mv.visitInsn(Opcodes.D2I);
cast(Type.INT_TYPE, to);
}
} else if (from == Type.FLOAT_TYPE) {
if (to == Type.DOUBLE_TYPE) {
mv.visitInsn(Opcodes.F2D);
} else if (to == Type.LONG_TYPE) {
mv.visitInsn(Opcodes.F2L);
} else {
mv.visitInsn(Opcodes.F2I);
cast(Type.INT_TYPE, to);
}
} else if (from == Type.LONG_TYPE) {
if (to == Type.DOUBLE_TYPE) {
mv.visitInsn(Opcodes.L2D);
} else if (to == Type.FLOAT_TYPE) {
mv.visitInsn(Opcodes.L2F);
} else {
mv.visitInsn(Opcodes.L2I);
cast(Type.INT_TYPE, to);
}
} else {
if (to == Type.BYTE_TYPE) {
mv.visitInsn(Opcodes.I2B);
} else if (to == Type.CHAR_TYPE) {
mv.visitInsn(Opcodes.I2C);
} else if (to == Type.DOUBLE_TYPE) {
mv.visitInsn(Opcodes.I2D);
} else if (to == Type.FLOAT_TYPE) {
mv.visitInsn(Opcodes.I2F);
} else if (to == Type.LONG_TYPE) {
mv.visitInsn(Opcodes.I2L);
} else if (to == Type.SHORT_TYPE) {
mv.visitInsn(Opcodes.I2S);
}
}
}
}
/**
* Generates the instructions to cast a numerical value from one type to another.
*
* @param from the type of the top stack value
* @param to the type into which this value must be cast.
*/
public void cast(final Type from, final Type to) {
if (from != to) {
if (from.getSort() < Type.BOOLEAN
|| from.getSort() > Type.DOUBLE
|| to.getSort() < Type.BOOLEAN
|| to.getSort() > Type.DOUBLE) {
throw new IllegalArgumentException("Cannot cast from " + from + " to " + to);
}
if (from == Type.DOUBLE_TYPE) {
if (to == Type.FLOAT_TYPE) {
mv.visitInsn(Opcodes.D2F);
} else if (to == Type.LONG_TYPE) {
mv.visitInsn(Opcodes.D2L);
} else {
mv.visitInsn(Opcodes.D2I);
cast(Type.INT_TYPE, to);
}
} else if (from == Type.FLOAT_TYPE) {
if (to == Type.DOUBLE_TYPE) {
mv.visitInsn(Opcodes.F2D);
} else if (to == Type.LONG_TYPE) {
mv.visitInsn(Opcodes.F2L);
} else {
mv.visitInsn(Opcodes.F2I);
cast(Type.INT_TYPE, to);
}
} else if (from == Type.LONG_TYPE) {
if (to == Type.DOUBLE_TYPE) {
mv.visitInsn(Opcodes.L2D);
} else if (to == Type.FLOAT_TYPE) {
mv.visitInsn(Opcodes.L2F);
} else {
mv.visitInsn(Opcodes.L2I);
cast(Type.INT_TYPE, to);
}
} else {
if (to == Type.BYTE_TYPE) {
mv.visitInsn(Opcodes.I2B);
} else if (to == Type.CHAR_TYPE) {
mv.visitInsn(Opcodes.I2C);
} else if (to == Type.DOUBLE_TYPE) {
mv.visitInsn(Opcodes.I2D);
} else if (to == Type.FLOAT_TYPE) {
mv.visitInsn(Opcodes.I2F);
} else if (to == Type.LONG_TYPE) {
mv.visitInsn(Opcodes.I2L);
} else if (to == Type.SHORT_TYPE) {
mv.visitInsn(Opcodes.I2S);
}
}
}
}
/**
* Generates the instruction to cast from the first given type to the other.
*
* @param from a Type.
* @param to a Type.
*/
public void cast(final Type from, final Type to) {
if (from != to) {
if (from == Type.DOUBLE_TYPE) {
if (to == Type.FLOAT_TYPE) {
mv.visitInsn(Opcodes.D2F);
} else if (to == Type.LONG_TYPE) {
mv.visitInsn(Opcodes.D2L);
} else {
mv.visitInsn(Opcodes.D2I);
cast(Type.INT_TYPE, to);
}
} else if (from == Type.FLOAT_TYPE) {
if (to == Type.DOUBLE_TYPE) {
mv.visitInsn(Opcodes.F2D);
} else if (to == Type.LONG_TYPE) {
mv.visitInsn(Opcodes.F2L);
} else {
mv.visitInsn(Opcodes.F2I);
cast(Type.INT_TYPE, to);
}
} else if (from == Type.LONG_TYPE) {
if (to == Type.DOUBLE_TYPE) {
mv.visitInsn(Opcodes.L2D);
} else if (to == Type.FLOAT_TYPE) {
mv.visitInsn(Opcodes.L2F);
} else {
mv.visitInsn(Opcodes.L2I);
cast(Type.INT_TYPE, to);
}
} else {
if (to == Type.BYTE_TYPE) {
mv.visitInsn(Opcodes.I2B);
} else if (to == Type.CHAR_TYPE) {
mv.visitInsn(Opcodes.I2C);
} else if (to == Type.DOUBLE_TYPE) {
mv.visitInsn(Opcodes.I2D);
} else if (to == Type.FLOAT_TYPE) {
mv.visitInsn(Opcodes.I2F);
} else if (to == Type.LONG_TYPE) {
mv.visitInsn(Opcodes.I2L);
} else if (to == Type.SHORT_TYPE) {
mv.visitInsn(Opcodes.I2S);
}
}
}
}
void recreateLocals(StackInfo info) {
if (info.localsSize() == 0)
return;
visitVarInsn(ALOAD, 0);
visitFieldInsn(GETFIELD, currentClassName, "__stack", "Ljava/util/Stack;");
visitVarInsn(ALOAD, 0);
visitFieldInsn(GETFIELD, currentClassName, "__stackPosition", "I");
visitMethodInsn(INVOKEVIRTUAL, "java/util/Stack", "get", "(I)Ljava/lang/Object;");
visitTypeInsn(CHECKCAST, "org/copperengine/core/StackEntry");
visitFieldInsn(GETFIELD, "org/copperengine/core/StackEntry", "locals", "[Ljava/lang/Object;");
for (int i = 0; i < info.localsSize(); ++i) {
Type t = info.getLocal(i);
if (t != null) {
if (t != StackInfo.AconstNullType) {
super.visitInsn(DUP);
super.visitIntInsn(SIPUSH, i);
super.visitInsn(AALOAD);
} else {
super.visitInsn(ACONST_NULL);
}
if (t == Type.BOOLEAN_TYPE || t == Type.BYTE_TYPE || t == Type.SHORT_TYPE || t == Type.INT_TYPE || t == Type.CHAR_TYPE) {
super.visitTypeInsn(CHECKCAST, Type.getInternalName(Integer.class));
super.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
super.visitVarInsn(ISTORE, i);
} else if (t == Type.FLOAT_TYPE) {
super.visitTypeInsn(CHECKCAST, Type.getInternalName(Float.class));
super.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false);
super.visitVarInsn(FSTORE, i);
} else if (t == Type.LONG_TYPE) {
super.visitTypeInsn(CHECKCAST, Type.getInternalName(Long.class));
super.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false);
super.visitVarInsn(LSTORE, i);
} else if (t == Type.DOUBLE_TYPE) {
super.visitTypeInsn(CHECKCAST, Type.getInternalName(Double.class));
super.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false);
super.visitVarInsn(DSTORE, i);
} else {
if (!t.getInternalName().equals(Type.getInternalName(Object.class)) && t != StackInfo.AconstNullType)
super.visitTypeInsn(CHECKCAST, t.getInternalName());
super.visitVarInsn(ASTORE, i);
}
}
}
visitInsn(POP);
}
private void recreateStack(StackInfo info) {
if (info.stackSize() == 0)
return;
visitVarInsn(ALOAD, 0);
visitFieldInsn(GETFIELD, currentClassName, "__stack", "Ljava/util/Stack;");
visitVarInsn(ALOAD, 0);
visitFieldInsn(GETFIELD, currentClassName, "__stackPosition", "I");
visitMethodInsn(INVOKEVIRTUAL, "java/util/Stack", "get", "(I)Ljava/lang/Object;");
visitTypeInsn(CHECKCAST, "org/copperengine/core/StackEntry");
visitFieldInsn(GETFIELD, "org/copperengine/core/StackEntry", "stack", "[Ljava/lang/Object;");
for (int i = 0; i < info.stackSize(); ++i) {
Type t = info.getStack(i);
if (t != null) {
if (t != StackInfo.AconstNullType) {
super.visitInsn(DUP);
super.visitIntInsn(SIPUSH, i);
super.visitInsn(AALOAD);
} else {
super.visitInsn(ACONST_NULL);
}
if (t == Type.BOOLEAN_TYPE || t == Type.BYTE_TYPE || t == Type.SHORT_TYPE || t == Type.INT_TYPE || t == Type.CHAR_TYPE) {
super.visitTypeInsn(CHECKCAST, Type.getInternalName(Integer.class));
super.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
super.visitInsn(SWAP);
} else if (t == Type.FLOAT_TYPE) {
super.visitTypeInsn(CHECKCAST, Type.getInternalName(Float.class));
super.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false);
super.visitInsn(SWAP);
} else if (t == Type.LONG_TYPE) {
super.visitTypeInsn(CHECKCAST, Type.getInternalName(Long.class));
super.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false);
super.visitInsn(DUP2_X1);
super.visitInsn(POP2);
} else if (t == Type.DOUBLE_TYPE) {
super.visitTypeInsn(CHECKCAST, Type.getInternalName(Double.class));
super.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false);
super.visitInsn(DUP2_X1);
super.visitInsn(POP2);
} else {
if (!t.getInternalName().equals(Type.getInternalName(Object.class)) && t != StackInfo.AconstNullType)
super.visitTypeInsn(CHECKCAST, t.getInternalName());
super.visitInsn(SWAP);
}
}
}
super.visitInsn(POP);
}