Search in sources :

Example 6 with RefType

use of soot.RefType in project robovm by robovm.

the class BroMethodCompiler method getStructMemberType.

public Type getStructMemberType(SootMethod method) {
    String methodType = hasStructMemberAnnotation(method) ? "@StructMember" : "@GlobalValue";
    SootMethod getter = method.getParameterCount() == 0 ? method : null;
    SootMethod setter = getter == null ? method : null;
    soot.Type type = getter != null ? getter.getReturnType() : setter.getParameterType(0);
    Type memberType = null;
    if (getter != null && hasPointerAnnotation(getter) || setter != null && hasPointerAnnotation(setter, 0)) {
        memberType = I8_PTR;
    } else if (getter != null && hasMachineSizedFloatAnnotation(getter) || setter != null && hasMachineSizedFloatAnnotation(setter, 0)) {
        memberType = config.getArch().is32Bit() ? FLOAT : DOUBLE;
    } else if (getter != null && (hasMachineSizedSIntAnnotation(getter) || hasMachineSizedUIntAnnotation(getter)) || setter != null && (hasMachineSizedSIntAnnotation(setter, 0) || hasMachineSizedUIntAnnotation(setter, 0))) {
        memberType = config.getArch().is32Bit() ? I32 : I64;
    } else if (type instanceof PrimType) {
        memberType = getType(type);
    } else if (getter != null && hasArrayAnnotation(getter) || setter != null && hasArrayAnnotation(setter, 0)) {
        int[] dimensions = getter != null ? getArrayDimensions(getter) : getArrayDimensions(setter, 0);
        if (dimensions == null || dimensions.length == 0) {
            throw new IllegalArgumentException("No dimensions specified for @Array annotation on " + methodType + " " + (getter != null ? "getter" : "setter") + " " + method);
        }
        if (type instanceof soot.ArrayType && ((soot.ArrayType) type).numDimensions != dimensions.length) {
            throw new IllegalArgumentException("Mismatch in number of dimennsions for @Array annotation " + "and type on " + methodType + " " + (getter != null ? "getter" : "setter") + " " + method);
        }
        Type baseType = null;
        if (type instanceof soot.ArrayType) {
            soot.ArrayType arrayType = (soot.ArrayType) type;
            if (isStruct(arrayType.baseType)) {
                // ByVal is implied for arrays of structs
                try {
                    baseType = getStructType(arrayType.baseType);
                } catch (StackOverflowError e) {
                    throw new IllegalArgumentException("Struct type " + type + " refers to itself");
                }
            } else {
                baseType = getType(arrayType.baseType);
            }
        } else if (isStruct(type)) {
            // ByVal is implied
            try {
                baseType = getStructType(type);
            } catch (StackOverflowError e) {
                throw new IllegalArgumentException("Struct type " + type + " refers to itself");
            }
        } else if (type instanceof RefType) {
            MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(getter != null ? new MarshalSite(getter) : new MarshalSite(setter, 0));
            baseType = getType(((ArrayMarshalerMethod) marshalerMethod).getBaseType());
        }
        if (baseType == null) {
            throw new IllegalArgumentException("Arrays of " + type + " is not supported");
        }
        long total = dimensions[0];
        for (int i = 1; i < dimensions.length; i++) {
            total *= dimensions[i];
        }
        memberType = new ArrayType(total, baseType);
    } else if (isStruct(type)) {
        boolean byVal = getter != null ? isPassByValue(getter) : isPassByValue(setter, 0);
        if (!byVal) {
            // NOTE: We use i8* instead of <StructType>* to support pointers to recursive structs
            memberType = I8_PTR;
        } else {
            try {
                memberType = getStructType(type);
            } catch (StackOverflowError e) {
                throw new IllegalArgumentException("Struct type " + type + " refers to itself");
            }
        }
    } else if (isNativeObject(type)) {
        memberType = I8_PTR;
    } else {
        MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(getter != null ? new MarshalSite(getter) : new MarshalSite(setter, 0));
        if (marshalerMethod instanceof ValueMarshalerMethod) {
            memberType = ((ValueMarshalerMethod) marshalerMethod).getNativeType(config.getArch());
        } else {
            memberType = I8_PTR;
        }
    }
    return memberType;
}
Also used : MarshalSite(org.robovm.compiler.MarshalerLookup.MarshalSite) ValueMarshalerMethod(org.robovm.compiler.MarshalerLookup.ValueMarshalerMethod) Ptrtoint(org.robovm.compiler.llvm.Ptrtoint) 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) SootMethod(soot.SootMethod) PrimType(soot.PrimType) MarshalerMethod(org.robovm.compiler.MarshalerLookup.MarshalerMethod) ValueMarshalerMethod(org.robovm.compiler.MarshalerLookup.ValueMarshalerMethod) ArrayMarshalerMethod(org.robovm.compiler.MarshalerLookup.ArrayMarshalerMethod) ArrayMarshalerMethod(org.robovm.compiler.MarshalerLookup.ArrayMarshalerMethod)

Example 7 with RefType

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

Aggregations

RefType (soot.RefType)7 SootClass (soot.SootClass)5 SootMethod (soot.SootMethod)5 PrimType (soot.PrimType)4 CompilerException (org.robovm.compiler.CompilerException)3 DoubleType (soot.DoubleType)3 FloatType (soot.FloatType)3 LongType (soot.LongType)3 VoidType (soot.VoidType)3 AggregateType (org.robovm.compiler.llvm.AggregateType)2 ArrayType (org.robovm.compiler.llvm.ArrayType)2 FunctionType (org.robovm.compiler.llvm.FunctionType)2 IntegerType (org.robovm.compiler.llvm.IntegerType)2 PointerType (org.robovm.compiler.llvm.PointerType)2 PrimitiveType (org.robovm.compiler.llvm.PrimitiveType)2 Ptrtoint (org.robovm.compiler.llvm.Ptrtoint)2 StructureType (org.robovm.compiler.llvm.StructureType)2 Type (org.robovm.compiler.llvm.Type)2 ArrayType (soot.ArrayType)2 ArrayList (java.util.ArrayList)1