Search in sources :

Example 16 with Type

use of org.robovm.compiler.llvm.Type 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 17 with Type

use of org.robovm.compiler.llvm.Type in project robovm by robovm.

the class BroMethodCompiler method getBridgeOrCallbackFunctionType.

private FunctionType getBridgeOrCallbackFunctionType(String anno, SootMethod method, boolean dynamic, boolean considerVariadic) {
    Type returnType = getReturnType(anno, method);
    boolean varargs = considerVariadic && hasVariadicAnnotation(method);
    int variadicIndex = varargs ? getVariadicParameterIndex(method) : Integer.MAX_VALUE;
    List<Type> paramTypes = new ArrayList<>();
    for (int i = dynamic ? 1 : 0; i < method.getParameterCount(); i++) {
        if (i == variadicIndex) {
            break;
        }
        paramTypes.add(getParameterType(anno, method, i));
    }
    if (!method.isStatic()) {
        int idx = hasStructRetAnnotation(method, 0) ? 1 : 0;
        soot.Type sootType = method.getDeclaringClass().getType();
        if (isStruct(sootType)) {
            paramTypes.add(idx, new PointerType(getStructType(sootType)));
        } else if (isNativeObject(sootType)) {
            // NativeObjects are always passed by reference.
            paramTypes.add(idx, I8_PTR);
        } else {
            throw new IllegalArgumentException("Receiver of non static " + anno + " method " + method + " must either be a Struct or a NativeObject");
        }
    }
    return new FunctionType(returnType, varargs, paramTypes.toArray(new Type[paramTypes.size()]));
}
Also used : 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) FunctionType(org.robovm.compiler.llvm.FunctionType) ArrayList(java.util.ArrayList) PointerType(org.robovm.compiler.llvm.PointerType) Ptrtoint(org.robovm.compiler.llvm.Ptrtoint)

Example 18 with Type

use of org.robovm.compiler.llvm.Type in project robovm by robovm.

the class Functions method callWithArguments.

public static Value callWithArguments(Function currentFunction, Value fn, Argument... args) {
    Variable result = null;
    Type returnType = ((FunctionType) fn.getType()).getReturnType();
    if (returnType != VOID) {
        result = currentFunction.newVariable(returnType);
    }
    currentFunction.add(new Call(result, fn, args));
    return result == null ? null : result.ref();
}
Also used : TailCall(org.robovm.compiler.llvm.TailCall) Call(org.robovm.compiler.llvm.Call) PointerType(org.robovm.compiler.llvm.PointerType) Type(org.robovm.compiler.llvm.Type) FunctionType(org.robovm.compiler.llvm.FunctionType) Variable(org.robovm.compiler.llvm.Variable) FunctionType(org.robovm.compiler.llvm.FunctionType)

Example 19 with Type

use of org.robovm.compiler.llvm.Type in project robovm by robovm.

the class Functions method invoke.

public static Value invoke(Function currentFunction, Value fn, BasicBlockRef success, BasicBlockRef failure, Value... args) {
    Variable result = null;
    Type returnType = ((FunctionType) fn.getType()).getReturnType();
    if (returnType != VOID) {
        result = currentFunction.newVariable(returnType);
    }
    currentFunction.add(new Invoke(result, fn, success, failure, args));
    return result == null ? null : result.ref();
}
Also used : PointerType(org.robovm.compiler.llvm.PointerType) Type(org.robovm.compiler.llvm.Type) FunctionType(org.robovm.compiler.llvm.FunctionType) Variable(org.robovm.compiler.llvm.Variable) FunctionType(org.robovm.compiler.llvm.FunctionType) Invoke(org.robovm.compiler.llvm.Invoke)

Example 20 with Type

use of org.robovm.compiler.llvm.Type in project robovm by robovm.

the class GlobalValueMethodCompiler method doCompile.

protected Function doCompile(ModuleBuilder moduleBuilder, SootMethod method) {
    AnnotationTag globalValueAnnotation = getAnnotation(method, GLOBAL_VALUE);
    validateGlobalValueMethod(method, globalValueAnnotation);
    boolean optional = readBooleanElem(globalValueAnnotation, "optional", false);
    boolean dereference = readBooleanElem(globalValueAnnotation, "dereference", true);
    Function fn = createMethodFunction(method);
    moduleBuilder.addFunction(fn);
    Type valueType = getStructMemberType(method);
    // Load the address of the resolved @GlobalValue method
    Variable valuePtr = fn.newVariable(new PointerType(valueType));
    Global valuePtrPtr = new Global(Symbols.globalValuePtrSymbol(method), _private, new NullConstant(I8_PTR));
    moduleBuilder.addGlobal(valuePtrPtr);
    fn.add(new Load(valuePtr, new ConstantBitcast(valuePtrPtr.ref(), new PointerType(valuePtr.getType()))));
    Label nullLabel = new Label();
    Label notNullLabel = new Label();
    Variable nullCheck = fn.newVariable(I1);
    fn.add(new Icmp(nullCheck, Condition.eq, valuePtr.ref(), new NullConstant(valuePtr.getType())));
    fn.add(new Br(nullCheck.ref(), fn.newBasicBlockRef(nullLabel), fn.newBasicBlockRef(notNullLabel)));
    fn.newBasicBlock(nullLabel);
    VariableRef env = fn.getParameterRef(0);
    call(fn, BC_THROW_UNSATISIFED_LINK_ERROR, env, moduleBuilder.getString(String.format((optional ? "Optional " : "") + "@GlobalValue method %s.%s%s not bound", className, method.getName(), getDescriptor(method))));
    fn.add(new Unreachable());
    fn.newBasicBlock(notNullLabel);
    if (method.getParameterCount() == 0) {
        // Getter
        Value result = loadValueForGetter(method, fn, valueType, valuePtr.ref(), env, dereference, MarshalerFlags.CALL_TYPE_GLOBAL_VALUE);
        fn.add(new Ret(result));
    } else {
        // Setter
        // 'env' is parameter 0, the value we're interested in is at index 1
        Value value = fn.getParameterRef(1);
        storeValueForSetter(method, fn, valueType, valuePtr.ref(), env, value, MarshalerFlags.CALL_TYPE_GLOBAL_VALUE);
        fn.add(new Ret());
    }
    return fn;
}
Also used : Ret(org.robovm.compiler.llvm.Ret) Load(org.robovm.compiler.llvm.Load) VariableRef(org.robovm.compiler.llvm.VariableRef) Variable(org.robovm.compiler.llvm.Variable) ConstantBitcast(org.robovm.compiler.llvm.ConstantBitcast) Label(org.robovm.compiler.llvm.Label) NullConstant(org.robovm.compiler.llvm.NullConstant) PointerType(org.robovm.compiler.llvm.PointerType) Global(org.robovm.compiler.llvm.Global) Br(org.robovm.compiler.llvm.Br) AnnotationTag(soot.tagkit.AnnotationTag) Function(org.robovm.compiler.llvm.Function) PointerType(org.robovm.compiler.llvm.PointerType) Type(org.robovm.compiler.llvm.Type) VoidType(soot.VoidType) Unreachable(org.robovm.compiler.llvm.Unreachable) Value(org.robovm.compiler.llvm.Value) Icmp(org.robovm.compiler.llvm.Icmp)

Aggregations

Type (org.robovm.compiler.llvm.Type)25 PointerType (org.robovm.compiler.llvm.PointerType)23 FunctionType (org.robovm.compiler.llvm.FunctionType)21 StructureType (org.robovm.compiler.llvm.StructureType)15 PrimType (soot.PrimType)15 IntegerType (org.robovm.compiler.llvm.IntegerType)14 LongType (soot.LongType)13 VoidType (soot.VoidType)13 ArrayList (java.util.ArrayList)12 Variable (org.robovm.compiler.llvm.Variable)11 DoubleType (soot.DoubleType)11 FloatType (soot.FloatType)11 ArrayType (org.robovm.compiler.llvm.ArrayType)10 CharType (soot.CharType)10 RefLikeType (soot.RefLikeType)10 AggregateType (org.robovm.compiler.llvm.AggregateType)8 PrimitiveType (org.robovm.compiler.llvm.PrimitiveType)8 RefType (soot.RefType)8 Value (org.robovm.compiler.llvm.Value)7 FunctionRef (org.robovm.compiler.llvm.FunctionRef)6