Search in sources :

Example 16 with PrimType

use of soot.PrimType in project soot by Sable.

the class ReflectiveCallsInliner method insertCastOrUnboxingCode.

private void insertCastOrUnboxingCode(Local lhs, Local rhs, Chain<Unit> newUnits) {
    // if assigning to a reference type then there's nothing to do
    if (lhs.getType() instanceof PrimType) {
        if ((rhs.getType() instanceof PrimType)) {
            // insert cast
            newUnits.add(Jimple.v().newAssignStmt(lhs, Jimple.v().newCastExpr(rhs, lhs.getType())));
        } else {
            // reference type in rhs; insert unboxing code
            RefType boxedType = (RefType) rhs.getType();
            SootMethodRef ref = Scene.v().makeMethodRef(boxedType.getSootClass(), lhs.getType().toString() + "Value", Collections.<Type>emptyList(), lhs.getType(), false);
            newUnits.add(Jimple.v().newAssignStmt(lhs, Jimple.v().newVirtualInvokeExpr(rhs, ref)));
        }
    }
}
Also used : RefType(soot.RefType) SootMethodRef(soot.SootMethodRef) PrimType(soot.PrimType)

Example 17 with PrimType

use of soot.PrimType in project robovm by robovm.

the class ObjCBlockPlugin method generateBridgeMethod.

private void generateBridgeMethod(Type[] actualGenericTypes, soot.Type[] unboxedTypes, String[][] targetMethodAnnotations, ClassWriter cw) {
    List<Type> genericParamTypes = new ArrayList<>();
    genericParamTypes.add(new SootTypeType(LongType.v()));
    genericParamTypes.add(new SootTypeType(org_robovm_objc_ObjCBlock.getType()));
    for (int i = 1; i < unboxedTypes.length; i++) {
        Type t = unboxedTypes[i] instanceof PrimType ? new SootTypeType(unboxedTypes[i]) : actualGenericTypes[i];
        genericParamTypes.add(t);
    }
    Type genericReturnType = unboxedTypes[0] instanceof PrimType ? new SootTypeType(unboxedTypes[0]) : actualGenericTypes[0];
    List<soot.Type> rawParamTypes = new ArrayList<>();
    rawParamTypes.add(LongType.v());
    rawParamTypes.add(org_robovm_objc_ObjCBlock.getType());
    rawParamTypes.addAll(Arrays.asList(unboxedTypes).subList(1, unboxedTypes.length));
    String name = "invoke";
    String signature = getGenericSignature(genericParamTypes, genericReturnType);
    String desc = getDescriptor(rawParamTypes, unboxedTypes[0]);
    MethodVisitor mv = cw.visitMethod(ACC_PRIVATE | ACC_STATIC | ACC_NATIVE, name, desc, signature, null);
    AnnotationVisitor av = mv.visitAnnotation(BRIDGE, true);
    av.visit("dynamic", true);
    av.visitEnd();
    for (String s : targetMethodAnnotations[0]) {
        mv.visitAnnotation(s, true).visitEnd();
    }
    for (int i = 1; i < targetMethodAnnotations.length; i++) {
        for (String s : targetMethodAnnotations[i]) {
            // We add 2 parameters first so annotations for the first 
            // parameter must be added at index 2.
            mv.visitParameterAnnotation(i + 1, s, true).visitEnd();
        }
    }
    mv.visitParameterAnnotation(0, POINTER, true).visitEnd();
    mv.visitEnd();
}
Also used : RefType(soot.RefType) ShortType(soot.ShortType) BooleanType(soot.BooleanType) SootTypeType(org.robovm.compiler.util.generic.SootTypeType) WildcardType(org.robovm.compiler.util.generic.WildcardType) SootMethodType(org.robovm.compiler.util.generic.SootMethodType) SootClassType(org.robovm.compiler.util.generic.SootClassType) ByteType(soot.ByteType) Type(org.robovm.compiler.util.generic.Type) DoubleType(soot.DoubleType) GenericArrayType(org.robovm.compiler.util.generic.GenericArrayType) FloatType(soot.FloatType) IntType(soot.IntType) ImplForType(org.robovm.compiler.util.generic.ImplForType) CharType(soot.CharType) LongType(soot.LongType) ParameterizedType(org.robovm.compiler.util.generic.ParameterizedType) PrimType(soot.PrimType) VoidType(soot.VoidType) SootTypeType(org.robovm.compiler.util.generic.SootTypeType) ArrayList(java.util.ArrayList) AnnotationVisitor(org.objectweb.asm.AnnotationVisitor) PrimType(soot.PrimType) MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 18 with PrimType

use of soot.PrimType in project robovm by robovm.

the class ObjCBlockPlugin method generateCallbackMethod.

private void generateCallbackMethod(String owner, SootMethod targetMethod, Type[] actualGenericTypes, soot.Type[] actualRawTypes, soot.Type[] unboxedTypes, Set<String> usedBoxMethods, Set<String> usedUnboxMethods, String[][] targetMethodAnnotations, ClassWriter cw) {
    String targetInterfaceName = Types.getInternalName(targetMethod.getDeclaringClass());
    List<Type> genericParamTypes = new ArrayList<>();
    genericParamTypes.add(new SootTypeType(org_robovm_objc_ObjCBlock.getType()));
    for (int i = 1; i < unboxedTypes.length; i++) {
        Type t = unboxedTypes[i] instanceof PrimType ? new SootTypeType(unboxedTypes[i]) : actualGenericTypes[i];
        genericParamTypes.add(t);
    }
    Type genericReturnType = unboxedTypes[0] instanceof PrimType ? new SootTypeType(unboxedTypes[0]) : actualGenericTypes[0];
    List<soot.Type> rawParamTypes = new ArrayList<>();
    rawParamTypes.add(org_robovm_objc_ObjCBlock.getType());
    rawParamTypes.addAll(Arrays.asList(unboxedTypes).subList(1, unboxedTypes.length));
    String name = "invoked";
    String signature = getGenericSignature(genericParamTypes, genericReturnType);
    String desc = getDescriptor(rawParamTypes, unboxedTypes[0]);
    MethodVisitor mv = cw.visitMethod(ACC_PRIVATE | ACC_STATIC, name, desc, signature, null);
    mv.visitAnnotation(CALLBACK, true).visitEnd();
    for (String s : targetMethodAnnotations[0]) {
        mv.visitAnnotation(s, true).visitEnd();
    }
    for (int i = 1; i < targetMethodAnnotations.length; i++) {
        for (String s : targetMethodAnnotations[i]) {
            // We add 1 parameter first so annotations for the first 
            // parameter should be added at index 1.
            mv.visitParameterAnnotation(i, s, true).visitEnd();
        }
    }
    mv.visitCode();
    mv.visitVarInsn(ALOAD, 0);
    mv.visitMethodInsn(INVOKEVIRTUAL, "org/robovm/objc/ObjCBlock", "object", "()Ljava/lang/Object;");
    mv.visitTypeInsn(CHECKCAST, targetInterfaceName);
    for (int i = 1, var = 1; i < actualRawTypes.length; i++, var++) {
        soot.Type from = unboxedTypes[i];
        if (from == LongType.v()) {
            mv.visitVarInsn(LLOAD, var);
            // longs need 2 slots
            var++;
        } else if (from == FloatType.v()) {
            mv.visitVarInsn(FLOAD, var);
        } else if (from == DoubleType.v()) {
            mv.visitVarInsn(DLOAD, var);
            // doubles need 2 slots
            var++;
        } else if (from instanceof PrimType) {
            // boolean, byte, short, char and int are loaded using ILOAD
            mv.visitVarInsn(ILOAD, var);
        } else {
            // Reference
            mv.visitVarInsn(ALOAD, var);
        }
        soot.Type to = actualRawTypes[i];
        if (from != to) {
            // Box the value on the top of the stack.
            String boxDesc = getDescriptor(Collections.singletonList(from), to);
            usedBoxMethods.add(boxDesc);
            mv.visitMethodInsn(INVOKESTATIC, owner, "box", boxDesc);
        }
    }
    // Now the receiver and all arguments are on the stack (boxed if needed). 
    // Call the target method.
    mv.visitMethodInsn(INVOKEINTERFACE, targetInterfaceName, targetMethod.getName(), getDescriptor(targetMethod));
    if (unboxedTypes[0] != actualRawTypes[0]) {
        mv.visitTypeInsn(CHECKCAST, getInternalName(actualRawTypes[0]));
        // Unbox the value on the top of the stack.
        String unboxDesc = getDescriptor(Collections.singletonList(actualRawTypes[0]), unboxedTypes[0]);
        usedUnboxMethods.add(unboxDesc);
        mv.visitMethodInsn(INVOKESTATIC, owner, "unbox", unboxDesc);
    }
    if (unboxedTypes[0] == VoidType.v()) {
        mv.visitInsn(RETURN);
    } else if (unboxedTypes[0] == LongType.v()) {
        mv.visitInsn(LRETURN);
    } else if (unboxedTypes[0] == FloatType.v()) {
        mv.visitInsn(FRETURN);
    } else if (unboxedTypes[0] == DoubleType.v()) {
        mv.visitInsn(DRETURN);
    } else if (unboxedTypes[0] instanceof PrimType) {
        mv.visitInsn(IRETURN);
    } else {
        mv.visitInsn(ARETURN);
    }
    mv.visitMaxs(0, 0);
    mv.visitEnd();
}
Also used : RefType(soot.RefType) ShortType(soot.ShortType) BooleanType(soot.BooleanType) SootTypeType(org.robovm.compiler.util.generic.SootTypeType) WildcardType(org.robovm.compiler.util.generic.WildcardType) SootMethodType(org.robovm.compiler.util.generic.SootMethodType) SootClassType(org.robovm.compiler.util.generic.SootClassType) ByteType(soot.ByteType) Type(org.robovm.compiler.util.generic.Type) DoubleType(soot.DoubleType) GenericArrayType(org.robovm.compiler.util.generic.GenericArrayType) FloatType(soot.FloatType) IntType(soot.IntType) ImplForType(org.robovm.compiler.util.generic.ImplForType) CharType(soot.CharType) LongType(soot.LongType) ParameterizedType(org.robovm.compiler.util.generic.ParameterizedType) PrimType(soot.PrimType) VoidType(soot.VoidType) SootTypeType(org.robovm.compiler.util.generic.SootTypeType) ArrayList(java.util.ArrayList) PrimType(soot.PrimType) MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 19 with PrimType

use of soot.PrimType in project robovm by robovm.

the class AnnotationImplPlugin method generateMemberFieldsAndAccessorMethods.

private void generateMemberFieldsAndAccessorMethods(Clazz clazz, ClassWriter cw) throws IOException {
    String implName = clazz.getInternalName() + IMPL_CLASS_NAME_SUFFIX;
    SootClass sootClass = clazz.getSootClass();
    List<SootMethod> methods = sootClass.getMethods();
    for (SootMethod method : methods) {
        String fieldName = getFieldName(method);
        soot.Type type = method.getReturnType();
        String typeDesc = Types.getDescriptor(type);
        // Add the field. Values are always stored as Object. If there was
        // an error in the annotation in the class file this will be an
        // Exception which will get thrown by the accessor method.
        cw.visitField(ACC_PRIVATE, fieldName, "Ljava/lang/Object;", null, null).visitEnd();
        // Add the public accessor method
        MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, method.getName(), Types.getDescriptor(method), null, null);
        mv.visitCode();
        // v = validate(<field>, <memberName>)
        mv.visitVarInsn(ALOAD, 0);
        mv.visitInsn(DUP);
        mv.visitFieldInsn(GETFIELD, implName, fieldName, "Ljava/lang/Object;");
        mv.visitLdcInsn(method.getName());
        mv.visitMethodInsn(INVOKESPECIAL, BASE_CLASS, "validate", "(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;");
        // return v (unboxed if needed)
        int retOp = 0;
        switch(typeDesc.charAt(0)) {
            case 'Z':
            case 'B':
            case 'S':
            case 'C':
            case 'I':
                retOp = IRETURN;
                break;
            case 'J':
                retOp = LRETURN;
                break;
            case 'F':
                retOp = FRETURN;
                break;
            case 'D':
                retOp = DRETURN;
                break;
            default:
                retOp = ARETURN;
                break;
        }
        unboxIfNeeded(mv, type);
        if (!(type instanceof PrimType)) {
            // Reference type
            mv.visitTypeInsn(CHECKCAST, Types.getInternalName(type));
        }
        mv.visitInsn(retOp);
        mv.visitMaxs(0, 0);
        mv.visitEnd();
    }
}
Also used : SootMethod(soot.SootMethod) PrimType(soot.PrimType) SootClass(soot.SootClass) MethodVisitor(org.objectweb.asm.MethodVisitor)

Example 20 with PrimType

use of soot.PrimType in project robovm by robovm.

the class AnnotationImplPlugin method generateSetDefaultsMethod.

private void generateSetDefaultsMethod(Clazz clazz, ClassWriter cw) {
    String implName = clazz.getInternalName() + IMPL_CLASS_NAME_SUFFIX;
    SootClass sootClass = clazz.getSootClass();
    List<SootMethod> methods = sootClass.getMethods();
    // Generate the $setDefaults() method which is called from the constructor
    // to set any default values
    MethodVisitor mv = cw.visitMethod(ACC_PRIVATE, "$setDefaults", "()V", null, null);
    mv.visitCode();
    for (SootMethod method : methods) {
        AnnotationDefaultTag defTag = (AnnotationDefaultTag) method.getTag(AnnotationDefaultTag.class.getSimpleName());
        String fieldName = getFieldName(method);
        if (defTag == null) {
            // No default value. Set field to super.NO_VALUE.
            mv.visitVarInsn(ALOAD, 0);
            mv.visitFieldInsn(GETSTATIC, BASE_CLASS, "NO_VALUE", "Ljava/lang/Object;");
            mv.visitFieldInsn(PUTFIELD, implName, fieldName, "Ljava/lang/Object;");
        } else {
            soot.Type type = method.getReturnType();
            String typeDesc = Types.getDescriptor(type);
            Object v = null;
            if (type instanceof PrimType) {
                switch(typeDesc.charAt(0)) {
                    case 'Z':
                    case 'B':
                    case 'S':
                    case 'C':
                    case 'I':
                        v = ((AnnotationIntElem) defTag.getDefaultVal()).getValue();
                        break;
                    case 'J':
                        v = ((AnnotationLongElem) defTag.getDefaultVal()).getValue();
                        break;
                    case 'F':
                        v = ((AnnotationFloatElem) defTag.getDefaultVal()).getValue();
                        break;
                    case 'D':
                        v = ((AnnotationDoubleElem) defTag.getDefaultVal()).getValue();
                        break;
                }
            } else if ("Ljava/lang/Class;".equals(typeDesc)) {
                v = Type.getType(((AnnotationClassElem) defTag.getDefaultVal()).getDesc());
                if (((Type) v).getDescriptor().length() != 1) {
                    // Only use a simple LDC for primitive classes (e.g. byte.class).
                    // Other classes may not be available at runtime. By falling back
                    // to Method.getDefaultValue() below we will get the proper
                    // exception at runtime.
                    v = null;
                }
            } else if ("Ljava/lang/String;".equals(typeDesc)) {
                v = ((AnnotationStringElem) defTag.getDefaultVal()).getValue();
            }
            if (v != null) {
                mv.visitVarInsn(ALOAD, 0);
                if (v instanceof Type && ((Type) v).getDescriptor().length() == 1) {
                    // LDC of primitive type class such as byte.class
                    switch(((Type) v).getDescriptor().charAt(0)) {
                        case 'V':
                            mv.visitFieldInsn(GETSTATIC, "java/lang/Void", "TYPE", "Ljava/lang/Class;");
                            break;
                        case 'Z':
                            mv.visitFieldInsn(GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;");
                            break;
                        case 'B':
                            mv.visitFieldInsn(GETSTATIC, "java/lang/Byte", "TYPE", "Ljava/lang/Class;");
                            break;
                        case 'S':
                            mv.visitFieldInsn(GETSTATIC, "java/lang/Short", "TYPE", "Ljava/lang/Class;");
                            break;
                        case 'C':
                            mv.visitFieldInsn(GETSTATIC, "java/lang/Character", "TYPE", "Ljava/lang/Class;");
                            break;
                        case 'I':
                            mv.visitFieldInsn(GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;");
                            break;
                        case 'J':
                            mv.visitFieldInsn(GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;");
                            break;
                        case 'F':
                            mv.visitFieldInsn(GETSTATIC, "java/lang/Float", "TYPE", "Ljava/lang/Class;");
                            break;
                        case 'D':
                            mv.visitFieldInsn(GETSTATIC, "java/lang/Double", "TYPE", "Ljava/lang/Class;");
                            break;
                    }
                } else {
                    mv.visitLdcInsn(v);
                }
                boxIfNeeded(mv, type);
                mv.visitFieldInsn(PUTFIELD, implName, fieldName, "Ljava/lang/Object;");
            } else {
                // Must be class, enum, array type or annotation. Fall back to super.getDefaultValue(<memberName>).
                mv.visitVarInsn(ALOAD, 0);
                mv.visitInsn(DUP);
                mv.visitLdcInsn(method.getName());
                mv.visitMethodInsn(INVOKESPECIAL, BASE_CLASS, "getDefaultValue", "(Ljava/lang/String;)Ljava/lang/Object;");
                mv.visitFieldInsn(PUTFIELD, implName, fieldName, "Ljava/lang/Object;");
            }
        }
    }
    mv.visitInsn(RETURN);
    mv.visitMaxs(0, 0);
    mv.visitEnd();
}
Also used : Type(org.objectweb.asm.Type) PrimType(soot.PrimType) AnnotationDefaultTag(soot.tagkit.AnnotationDefaultTag) SootMethod(soot.SootMethod) PrimType(soot.PrimType) SootClass(soot.SootClass) MethodVisitor(org.objectweb.asm.MethodVisitor)

Aggregations

PrimType (soot.PrimType)31 RefType (soot.RefType)15 ArrayList (java.util.ArrayList)12 Type (soot.Type)10 Value (soot.Value)10 DoubleType (soot.DoubleType)9 FloatType (soot.FloatType)9 IntType (soot.IntType)9 Local (soot.Local)9 LongType (soot.LongType)9 BooleanType (soot.BooleanType)8 SootClass (soot.SootClass)8 SootMethod (soot.SootMethod)8 ByteType (soot.ByteType)7 CharType (soot.CharType)7 ShortType (soot.ShortType)7 ArrayType (soot.ArrayType)6 VoidType (soot.VoidType)6 MethodVisitor (org.objectweb.asm.MethodVisitor)4 PointerType (org.robovm.compiler.llvm.PointerType)4