Search in sources :

Example 31 with SootClass

use of soot.SootClass 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 32 with SootClass

use of soot.SootClass 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)

Example 33 with SootClass

use of soot.SootClass in project robovm by robovm.

the class TrampolineCompiler method resolveMethod.

private SootMethod resolveMethod(SootClass clazz, String name, String desc) {
    if (clazz != null && !clazz.isPhantom()) {
        SootMethod method = getMethod(clazz, name, desc);
        if (method != null) {
            return method;
        }
        if (name.equals("sizeOf") && isStruct(clazz)) {
            method = new SootMethod("sizeOf", Collections.EMPTY_LIST, IntType.v(), Modifier.PUBLIC | Modifier.STATIC);
            method.setDeclaringClass(clazz);
            method.setDeclared(true);
            return method;
        }
        SootClass c = !clazz.isInterface() && clazz.hasSuperclass() ? clazz.getSuperclass() : null;
        while (c != null) {
            method = getMethod(c, name, desc);
            if (method != null) {
                return method;
            }
            c = !c.isInterface() && c.hasSuperclass() ? c.getSuperclass() : null;
        }
        c = clazz;
        while (c != null) {
            for (SootClass interfaze : c.getInterfaces()) {
                method = resolveInterfaceMethod(interfaze, name, desc);
                if (method != null) {
                    return method;
                }
            }
            c = !c.isInterface() && c.hasSuperclass() ? c.getSuperclass() : null;
        }
    }
    return null;
}
Also used : SootMethod(soot.SootMethod) SootClass(soot.SootClass)

Example 34 with SootClass

use of soot.SootClass in project robovm by robovm.

the class TrampolineCompiler method resolveInterfaceMethod.

private SootMethod resolveInterfaceMethod(Function f, Invokeinterface t) {
    SootClass target = config.getClazzes().load(t.getTarget()).getSootClass();
    String name = t.getMethodName();
    String desc = t.getMethodDesc();
    if (!target.isInterface()) {
        throwIncompatibleChangeError(f, EXPECTED_INTERFACE_BUT_FOUND_CLASS, target);
        return null;
    }
    if ("<clinit>".equals(name) || "<init>".equals(name)) {
        // This is not part of interface method resolution but we 
        // need to handle it somehow.
        throwNoSuchMethodError(f, t);
        return null;
    }
    SootMethod method = resolveInterfaceMethod(target, name, desc);
    if (method == null) {
        SootClass javaLangObject = config.getClazzes().load("java/lang/Object").getSootClass();
        method = getMethod(javaLangObject, name, desc);
    }
    if (method == null) {
        throwNoSuchMethodError(f, t);
        return null;
    }
    if (method.isStatic()) {
        throwIncompatibleChangeError(f, EXPECTED_NON_STATIC_METHOD, target, name, desc);
        return null;
    }
    return method;
}
Also used : SootMethod(soot.SootMethod) SootClass(soot.SootClass)

Example 35 with SootClass

use of soot.SootClass in project robovm by robovm.

the class MarshalerLookup method findMarshalers.

public Marshaler findMarshalers(MarshalSite marshalSite) {
    soot.Type type = marshalSite.getType();
    SootClass sc = null;
    if (type instanceof RefType) {
        sc = ((RefType) type).getSootClass();
    } else if (type instanceof ArrayType && ((ArrayType) type).baseType instanceof RefType) {
        sc = ((RefType) ((ArrayType) type).baseType).getSootClass();
    }
    List<Marshaler> result = new ArrayList<>();
    Set<String> visited = new HashSet<>();
    Set<String> seen = new HashSet<>();
    if (sc != null) {
        findMarshalers(sc, result, visited, seen, false);
    }
    findMarshalers(marshalSite.method.getDeclaringClass(), result, visited, seen, searchBuiltins);
    for (Marshaler marshaler : result) {
        if (marshaler.canMarshal(marshalSite)) {
            return marshaler;
        }
    }
    return null;
}
Also used : RefType(soot.RefType) ArrayType(soot.ArrayType) ArrayList(java.util.ArrayList) SootClass(soot.SootClass) HashSet(java.util.HashSet)

Aggregations

SootClass (soot.SootClass)48 SootMethod (soot.SootMethod)30 Test (org.junit.Test)15 ArrayList (java.util.ArrayList)9 PrimType (soot.PrimType)9 RefType (soot.RefType)8 SootField (soot.SootField)7 HashSet (java.util.HashSet)6 ConstantBitcast (org.robovm.compiler.llvm.ConstantBitcast)4 Global (org.robovm.compiler.llvm.Global)4 IntegerConstant (org.robovm.compiler.llvm.IntegerConstant)4 Type (org.robovm.compiler.llvm.Type)4 File (java.io.File)3 CompilerException (org.robovm.compiler.CompilerException)3 Entry (org.robovm.compiler.VTable.Entry)3 ArrayType (org.robovm.compiler.llvm.ArrayType)3 NullConstant (org.robovm.compiler.llvm.NullConstant)3 PointerType (org.robovm.compiler.llvm.PointerType)3 StructureConstant (org.robovm.compiler.llvm.StructureConstant)3 StructureConstantBuilder (org.robovm.compiler.llvm.StructureConstantBuilder)3