Search in sources :

Example 26 with SootClass

use of soot.SootClass in project robovm by robovm.

the class VTableTest method testObject.

@Test
public void testObject() {
    SootClass sc = getSootClass("java.lang.Object");
    VTable.Cache cache = new VTable.Cache();
    VTable vtable = cache.get(sc);
    assertEquals(11, vtable.size());
    assertNotNull(vtable.findEntry("toString", "()Ljava/lang/String;"));
}
Also used : SootClass(soot.SootClass) Test(org.junit.Test)

Example 27 with SootClass

use of soot.SootClass in project robovm by robovm.

the class ClassCompiler method createClassInfoStruct.

private StructureConstant createClassInfoStruct() {
    int flags = 0;
    if (Modifier.isPublic(sootClass.getModifiers())) {
        flags |= CI_PUBLIC;
    }
    if (Modifier.isFinal(sootClass.getModifiers())) {
        flags |= CI_FINAL;
    }
    if (Modifier.isInterface(sootClass.getModifiers())) {
        flags |= CI_INTERFACE;
    }
    if (Modifier.isAbstract(sootClass.getModifiers())) {
        flags |= CI_ABSTRACT;
    }
    if ((sootClass.getModifiers() & 0x1000) > 0) {
        flags |= CI_SYNTHETIC;
    }
    if (Modifier.isAnnotation(sootClass.getModifiers())) {
        flags |= CI_ANNOTATION;
    }
    if (Modifier.isEnum(sootClass.getModifiers())) {
        flags |= CI_ENUM;
    }
    if (attributesEncoder.classHasAttributes()) {
        flags |= CI_ATTRIBUTES;
    }
    if (hasFinalizer(sootClass)) {
        flags |= CI_FINALIZABLE;
    }
    // Create the ClassInfoHeader structure.
    StructureConstantBuilder header = new StructureConstantBuilder();
    // Points to the runtime Class struct
    header.add(new NullConstant(I8_PTR));
    header.add(new IntegerConstant(flags));
    header.add(getString(getInternalName(sootClass)));
    if (sootClass.declaresMethod("<clinit>", Collections.emptyList(), VoidType.v())) {
        SootMethod method = sootClass.getMethod("<clinit>", Collections.emptyList(), VoidType.v());
        header.add(new FunctionRef(Symbols.methodSymbol(method), getFunctionType(method)));
    } else {
        header.add(new NullConstant(I8_PTR));
    }
    mb.addGlobal(new Global(Symbols.typeInfoSymbol(getInternalName(sootClass)), Linkage.external, I8_PTR, true));
    // TypeInfo* generated by Linker
    header.add(new GlobalRef(Symbols.typeInfoSymbol(getInternalName(sootClass)), I8_PTR));
    if (!sootClass.isInterface()) {
        header.add(createVTableStruct());
    } else {
        header.add(createITableStruct());
    }
    header.add(createITablesStruct());
    header.add(sizeof(classType));
    header.add(sizeof(instanceType));
    if (!instanceFields.isEmpty()) {
        header.add(offsetof(instanceType, 1, 1));
    } else {
        header.add(sizeof(instanceType));
    }
    header.add(new IntegerConstant((short) countReferences(classFields)));
    header.add(new IntegerConstant((short) countReferences(instanceFields)));
    PackedStructureConstantBuilder body = new PackedStructureConstantBuilder();
    body.add(new IntegerConstant((short) sootClass.getInterfaceCount()));
    body.add(new IntegerConstant((short) sootClass.getFieldCount()));
    body.add(new IntegerConstant((short) sootClass.getMethodCount()));
    if (!sootClass.isInterface()) {
        body.add(getStringOrNull(sootClass.hasSuperclass() ? getInternalName(sootClass.getSuperclass()) : null));
    }
    if (attributesEncoder.classHasAttributes()) {
        body.add(new ConstantBitcast(attributesEncoder.getClassAttributes().ref(), I8_PTR));
    }
    for (SootClass s : sootClass.getInterfaces()) {
        body.add(getString(getInternalName(s)));
    }
    for (SootField f : sootClass.getFields()) {
        flags = 0;
        soot.Type t = f.getType();
        if (t instanceof PrimType) {
            if (t.equals(BooleanType.v())) {
                flags |= DESC_Z;
            } else if (t.equals(ByteType.v())) {
                flags |= DESC_B;
            } else if (t.equals(ShortType.v())) {
                flags |= DESC_S;
            } else if (t.equals(CharType.v())) {
                flags |= DESC_C;
            } else if (t.equals(IntType.v())) {
                flags |= DESC_I;
            } else if (t.equals(LongType.v())) {
                flags |= DESC_J;
            } else if (t.equals(FloatType.v())) {
                flags |= DESC_F;
            } else if (t.equals(DoubleType.v())) {
                flags |= DESC_D;
            }
            flags <<= 12;
        }
        if (Modifier.isPublic(f.getModifiers())) {
            flags |= FI_PUBLIC;
        } else if (Modifier.isPrivate(f.getModifiers())) {
            flags |= FI_PRIVATE;
        } else if (Modifier.isProtected(f.getModifiers())) {
            flags |= FI_PROTECTED;
        }
        if (Modifier.isStatic(f.getModifiers())) {
            flags |= FI_STATIC;
        }
        if (Modifier.isFinal(f.getModifiers())) {
            flags |= FI_FINAL;
        }
        if (Modifier.isVolatile(f.getModifiers())) {
            flags |= FI_VOLATILE;
        }
        if (Modifier.isTransient(f.getModifiers())) {
            flags |= FI_TRANSIENT;
        }
        if ((f.getModifiers() & 0x1000) > 0) {
            flags |= FI_SYNTHETIC;
        }
        if (Modifier.isEnum(f.getModifiers())) {
            flags |= FI_ENUM;
        }
        if (attributesEncoder.fieldHasAttributes(f)) {
            flags |= FI_ATTRIBUTES;
        }
        body.add(new IntegerConstant((short) flags));
        body.add(getString(f.getName()));
        if (!(t instanceof PrimType)) {
            body.add(getString(getDescriptor(f)));
        }
        if (f.isStatic()) {
            int index = classFields.indexOf(f);
            body.add(offsetof(classType, 1, index, 1));
        } else {
            int index = instanceFields.indexOf(f);
            body.add(offsetof(instanceType, 1, 1 + index, 1));
        }
        if (attributesEncoder.fieldHasAttributes(f)) {
            body.add(new ConstantBitcast(attributesEncoder.getFieldAttributes(f).ref(), I8_PTR));
        }
    }
    VTable vtable = !sootClass.isInterface() ? config.getVTableCache().get(sootClass) : null;
    ITable itable = sootClass.isInterface() ? config.getITableCache().get(sootClass) : null;
    ;
    for (SootMethod m : sootClass.getMethods()) {
        soot.Type t = m.getReturnType();
        flags = 0;
        if (Modifier.isPublic(m.getModifiers())) {
            flags |= MI_PUBLIC;
        } else if (Modifier.isPrivate(m.getModifiers())) {
            flags |= MI_PRIVATE;
        } else if (Modifier.isProtected(m.getModifiers())) {
            flags |= MI_PROTECTED;
        }
        if (Modifier.isStatic(m.getModifiers())) {
            flags |= MI_STATIC;
        }
        if (Modifier.isFinal(m.getModifiers())) {
            flags |= MI_FINAL;
        }
        if (Modifier.isSynchronized(m.getModifiers())) {
            flags |= MI_SYNCHRONIZED;
        }
        if ((m.getModifiers() & 0x0040) > 0) {
            flags |= MI_BRIDGE;
        }
        if ((m.getModifiers() & 0x0080) > 0) {
            flags |= MI_VARARGS;
        }
        if (Modifier.isNative(m.getModifiers())) {
            if (!isStruct(sootClass) && !hasStructMemberAnnotation(m)) {
                flags |= MI_NATIVE;
            }
        }
        if (Modifier.isAbstract(m.getModifiers())) {
            flags |= MI_ABSTRACT;
        }
        if (Modifier.isStrictFP(m.getModifiers())) {
            flags |= MI_STRICT;
        }
        if ((m.getModifiers() & 0x1000) > 0) {
            flags |= MI_SYNTHETIC;
        }
        if (attributesEncoder.methodHasAttributes(m)) {
            flags |= MI_ATTRIBUTES;
        }
        if (hasBridgeAnnotation(m) || hasGlobalValueAnnotation(m)) {
            flags |= MI_BRO_BRIDGE;
        }
        if (hasCallbackAnnotation(m)) {
            flags |= MI_BRO_CALLBACK;
        }
        if ((t instanceof PrimType || t == VoidType.v()) && m.getParameterCount() == 0) {
            flags |= MI_COMPACT_DESC;
        }
        body.add(new IntegerConstant((short) flags));
        Constant viTableIndex = new IntegerConstant((short) -1);
        if (vtable != null) {
            VTable.Entry entry = vtable.getEntry(m);
            if (entry != null) {
                viTableIndex = new IntegerConstant((short) entry.getIndex());
            }
        } else {
            ITable.Entry entry = itable.getEntry(m);
            if (entry != null) {
                viTableIndex = new IntegerConstant((short) entry.getIndex());
            }
        }
        body.add(viTableIndex);
        body.add(getString(m.getName()));
        if ((flags & MI_COMPACT_DESC) > 0) {
            int desc = 0;
            if (t.equals(BooleanType.v())) {
                desc = DESC_Z;
            } else if (t.equals(ByteType.v())) {
                desc = DESC_B;
            } else if (t.equals(ShortType.v())) {
                desc = DESC_S;
            } else if (t.equals(CharType.v())) {
                desc = DESC_C;
            } else if (t.equals(IntType.v())) {
                desc = DESC_I;
            } else if (t.equals(LongType.v())) {
                desc = DESC_J;
            } else if (t.equals(FloatType.v())) {
                desc = DESC_F;
            } else if (t.equals(DoubleType.v())) {
                desc = DESC_D;
            } else if (t.equals(VoidType.v())) {
                desc = DESC_V;
            }
            body.add(new IntegerConstant((byte) desc));
        } else {
            body.add(getString(getDescriptor(m)));
        }
        if (attributesEncoder.methodHasAttributes(m)) {
            body.add(new ConstantBitcast(attributesEncoder.getMethodAttributes(m).ref(), I8_PTR));
        }
        if (!m.isAbstract()) {
            body.add(new ConstantBitcast(new FunctionRef(Symbols.methodSymbol(m), getFunctionType(m)), I8_PTR));
            // Size of function. This value will be modified later by patching the .s file.
            body.add(new IntegerConstant(DUMMY_METHOD_SIZE));
            if (m.isSynchronized()) {
                body.add(new ConstantBitcast(new FunctionRef(Symbols.synchronizedWrapperSymbol(m), getFunctionType(m)), I8_PTR));
            }
            if ((flags & MI_NATIVE) == 0) {
                // Cannot use m.isNative() in the condition above since methods which are native in the
                // Java class file may have been changed to non-native by the RoboVM compiler 
                // (e.g. @StructMember methods). The native code which parses the info structs will see 
                // the method as non-native.
                // Add a weak linetable pointer which points to a -1 value which will be interpreted as 0 linenumbers in the table
                Global linetableGlobal = new Global(Symbols.linetableSymbol(m), Linkage.weak, new IntegerConstant(-1));
                mb.addGlobal(linetableGlobal);
                body.add(linetableGlobal.ref());
            }
        }
        if (hasBridgeAnnotation(m)) {
            if (!readBooleanElem(getAnnotation(m, BRIDGE), "dynamic", false)) {
                body.add(new GlobalRef(Symbols.bridgePtrSymbol(m), I8_PTR));
            } else {
                body.add(new NullConstant(I8_PTR));
            }
        } else if (hasGlobalValueAnnotation(m)) {
            body.add(new GlobalRef(Symbols.globalValuePtrSymbol(m), I8_PTR));
        }
        if (hasCallbackAnnotation(m)) {
            body.add(new AliasRef(Symbols.callbackPtrSymbol(m), I8_PTR));
        }
    }
    // after sizeof(ClassInfoHeader) bytes.
    return new StructureConstantBuilder().add(header.build()).add(body.build()).build();
}
Also used : GlobalRef(org.robovm.compiler.llvm.GlobalRef) PackedStructureConstantBuilder(org.robovm.compiler.llvm.PackedStructureConstantBuilder) AliasRef(org.robovm.compiler.llvm.AliasRef) StructureConstant(org.robovm.compiler.llvm.StructureConstant) Constant(org.robovm.compiler.llvm.Constant) NullConstant(org.robovm.compiler.llvm.NullConstant) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant) ConstantBitcast(org.robovm.compiler.llvm.ConstantBitcast) NullConstant(org.robovm.compiler.llvm.NullConstant) SootClass(soot.SootClass) StructureConstantBuilder(org.robovm.compiler.llvm.StructureConstantBuilder) PackedStructureConstantBuilder(org.robovm.compiler.llvm.PackedStructureConstantBuilder) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant) Global(org.robovm.compiler.llvm.Global) SootMethod(soot.SootMethod) PrimType(soot.PrimType) SootField(soot.SootField) FunctionRef(org.robovm.compiler.llvm.FunctionRef)

Example 28 with SootClass

use of soot.SootClass in project robovm by robovm.

the class BroMethodCompiler method getStructType.

private StructureType getStructType(SootClass clazz, boolean checkEmpty) {
    int n = 0;
    for (SootMethod method : clazz.getMethods()) {
        n = Math.max(getStructMemberOffset(method) + 1, n);
    }
    Type[] result = new Type[n + 1];
    StructureType superType = null;
    if (clazz.hasSuperclass()) {
        SootClass superclass = clazz.getSuperclass();
        if (!superclass.getName().equals("org.robovm.rt.bro.Struct")) {
            superType = getStructType(superclass, false);
        }
    }
    result[0] = superType != null ? superType : new StructureType();
    for (SootMethod method : clazz.getMethods()) {
        int offset = getStructMemberOffset(method);
        if (offset != -1) {
            if (!method.isNative() && !method.isStatic()) {
                throw new IllegalArgumentException("@StructMember annotated method " + method + " must be native and not static");
            }
            Type type = null;
            if (method.getParameterCount() == 0) {
                soot.Type sootType = method.getReturnType();
                // Possibly a getter
                if (hasPointerAnnotation(method) && !sootType.equals(LongType.v())) {
                    throw new IllegalArgumentException("@StructMember(" + offset + ") annotated getter " + method + " must be of type long when annotated with @Pointer");
                }
                if (hasMachineSizedFloatAnnotation(method) && !sootType.equals(DoubleType.v()) && !sootType.equals(FloatType.v())) {
                    throw new IllegalArgumentException("@StructMember(" + offset + ") annotated getter " + method + " must be of type float or double when annotated with @MachineSizedFloat");
                }
                if ((hasMachineSizedSIntAnnotation(method) || hasMachineSizedUIntAnnotation(method)) && !sootType.equals(LongType.v())) {
                    throw new IllegalArgumentException("@StructMember(" + offset + ") annotated getter " + method + " must be of type long when annotated with @MachineSizedSInt or @MachineSizedUInt");
                }
                if (sootType instanceof soot.ArrayType && !hasArrayAnnotation(method)) {
                    throw new IllegalArgumentException("@Array annotation expected on struct member getter " + method);
                }
            } else if (method.getParameterCount() == 1) {
                soot.Type sootType = method.getParameterType(0);
                if (hasPointerAnnotation(method, 0) && !sootType.equals(LongType.v())) {
                    throw new IllegalArgumentException("@StructMember(" + offset + ") annotated setter " + method + " must be of type long when annotated with @Pointer");
                }
                if (hasMachineSizedFloatAnnotation(method, 0) && !sootType.equals(DoubleType.v()) && !sootType.equals(FloatType.v())) {
                    throw new IllegalArgumentException("@StructMember(" + offset + ") annotated setter " + method + " must be of type float or double when annotated with @MachineSizedFloat");
                }
                if ((hasMachineSizedSIntAnnotation(method, 0) || hasMachineSizedUIntAnnotation(method)) && !sootType.equals(LongType.v())) {
                    throw new IllegalArgumentException("@StructMember(" + offset + ") annotated setter " + method + " must be of type long when annotated with @MachineSizedSInt or @MachineSizedUInt");
                }
                if (sootType instanceof soot.ArrayType && !hasArrayAnnotation(method, 0)) {
                    throw new IllegalArgumentException("@Array annotation expected on first parameter of struct member setter " + method);
                }
                soot.Type retType = method.getReturnType();
                // The return type of the setter must be void or this
                if (!retType.equals(VoidType.v()) && !(retType instanceof RefType && ((RefType) retType).getSootClass().equals(clazz))) {
                    throw new IllegalArgumentException("Setter " + method + " for " + "@StructMember(" + offset + ") " + " must either return nothing or return a " + clazz);
                }
            } else {
                throw new IllegalArgumentException("@StructMember annotated method " + method + " has too many parameters");
            }
            type = getStructMemberType(method);
            int index = offset + 1;
            if (result[index] == null) {
                result[index] = type;
            } else if (type != result[index]) {
                // Two members mapped to the same offset (union). Pick
                // the type with the largest alignment and pad with bytes
                // up to the largest size.
                result[index] = mergeStructMemberTypes(config.getDataLayout(), type, result[index]);
            }
        }
    }
    for (int i = 1; i < result.length; i++) {
        if (result[i] == null) {
            throw new IllegalArgumentException("No @StructMember(" + i + ") defined in class " + clazz);
        }
    }
    if (!clazz.isAbstract() && checkEmpty && n == 0 && superType == null) {
        throw new IllegalArgumentException("Struct class " + clazz + " has no @StructMember annotated methods");
    }
    return new StructureType(result);
}
Also used : ArrayType(org.robovm.compiler.llvm.ArrayType) RefType(soot.RefType) RefType(soot.RefType) IntegerType(org.robovm.compiler.llvm.IntegerType) StructureType(org.robovm.compiler.llvm.StructureType) ArrayType(org.robovm.compiler.llvm.ArrayType) PointerType(org.robovm.compiler.llvm.PointerType) DoubleType(soot.DoubleType) FloatType(soot.FloatType) LongType(soot.LongType) Type(org.robovm.compiler.llvm.Type) AggregateType(org.robovm.compiler.llvm.AggregateType) PrimitiveType(org.robovm.compiler.llvm.PrimitiveType) PrimType(soot.PrimType) VoidType(soot.VoidType) FunctionType(org.robovm.compiler.llvm.FunctionType) StructureType(org.robovm.compiler.llvm.StructureType) SootMethod(soot.SootMethod) SootClass(soot.SootClass) Ptrtoint(org.robovm.compiler.llvm.Ptrtoint)

Example 29 with SootClass

use of soot.SootClass in project robovm by robovm.

the class ObjCMemberPlugin method findOverriddenMethods.

private List<SootMethod> findOverriddenMethods(SootClass sootClass, SootMethod method) {
    SootClass supercls = sootClass.getSuperclass();
    while (!supercls.getType().equals(org_robovm_objc_ObjCObject.getType())) {
        try {
            SootMethod m = supercls.getMethod(method.getName(), method.getParameterTypes(), method.getReturnType());
            if (overrides(method, m) && !hasAnnotation(m, NOT_IMPLEMENTED)) {
                return Collections.singletonList(m);
            }
        } catch (RuntimeException e) {
        // Soot throws RuntimeException if method not found
        }
        supercls = supercls.getSuperclass();
    }
    /*
         * Method doesn't override any method in superclasses. Check interfaces
         * as well. There may be several methods in interfaces which this method
         * overrides. We have to return all of them as we cannot assume that
         * first one found has the @Method or @Property annotation.
         */
    List<SootMethod> candidates = new ArrayList<>();
    findOverriddenMethodsOnInterfaces(sootClass, method, candidates);
    return candidates;
}
Also used : ArrayList(java.util.ArrayList) SootMethod(soot.SootMethod) SootClass(soot.SootClass)

Example 30 with SootClass

use of soot.SootClass in project robovm by robovm.

the class TypeEncoder method getStructMembers.

private List<Member> getStructMembers(SootClass clazz, boolean is64bit) {
    List<Member> members = new ArrayList<>();
    if (clazz.hasSuperclass()) {
        SootClass superclass = clazz.getSuperclass();
        if (!superclass.getName().equals("org.robovm.rt.bro.Struct")) {
            members.addAll(getStructMembers(clazz, is64bit));
        }
    }
    for (SootMethod method : clazz.getMethods()) {
        int offset = getStructMemberOffset(method);
        if (offset != -1) {
            if (!method.isNative() && !method.isStatic()) {
                // thrown by the ClassCompiler later on.
                continue;
            }
            Type type;
            int idx;
            if (method.getParameterCount() == 0) {
                type = method.getReturnType();
                idx = -1;
            } else if (method.getParameterCount() == 1) {
                type = method.getParameterType(0);
                idx = 0;
            } else {
                // throw by the ClassCompiler later on.
                continue;
            }
            Member member = new Member();
            member.offset = offset;
            member.type = encodeOne(method, type, idx, is64bit);
            members.add(member);
        }
    }
    return members;
}
Also used : RefType(soot.RefType) Type(soot.Type) PrimType(soot.PrimType) VoidType(soot.VoidType) ArrayList(java.util.ArrayList) SootMethod(soot.SootMethod) SootClass(soot.SootClass)

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