Search in sources :

Example 6 with Type

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

use of org.robovm.compiler.util.generic.Type in project robovm by robovm.

the class ObjCBlockPlugin method resolveActualTypeArgs.

/**
     * Resolves the actual generic type arguments for a base class, as viewed from a subclass or implementation.
     * 
     * @param offspring class or interface subclassing or extending the base type
     * @param base base class
     * @param actualArgs the actual type arguments passed to the offspring class
     * @return actual generic type arguments, must match the type parameters of the offspring class. If omitted, the
     * type parameters will be used instead.
     * 
     * This code was copied from
     * http://stackoverflow.com/questions/17297308/how-do-i-resolve-the-actual-type-for-a-generic-return-type-using-reflection
     * and changed slightly.
     */
protected static Type[] resolveActualTypeArgs(SootClassType offspring, SootClassType base, Type... actualArgs) {
    TypeVariable<?>[] typeParameters = offspring.getTypeParameters();
    //  If actual types are omitted, the type parameters will be used instead.
    if (actualArgs.length == 0) {
        actualArgs = typeParameters;
    }
    // map type parameters into the actual types
    Map<String, Type> typeVariables = new HashMap<>();
    for (int i = 0; i < actualArgs.length; i++) {
        TypeVariable<?> typeVariable = (TypeVariable<?>) typeParameters[i];
        Type t = actualArgs[i];
        if (t instanceof WildcardType) {
            // If actual arg is ? it will have an upper bound of java.lang.Object but the
            // TypeVariable could specify a more specific type.
            Type upper = ((WildcardType) t).getUpperBounds()[0];
            if (upper instanceof SootClassType) {
                if ("java.lang.Object".equals(((SootClassType) upper).getSootClass().getName())) {
                    actualArgs[i] = typeVariable.getBounds()[0];
                }
            }
        }
        typeVariables.put(typeVariable.getName(), actualArgs[i]);
    }
    // Find direct ancestors (superclass, interfaces)
    List<Type> ancestors = new LinkedList<Type>();
    if (offspring.getGenericSuperclass() != null) {
        ancestors.add(offspring.getGenericSuperclass());
    }
    for (Type t : offspring.getGenericInterfaces()) {
        ancestors.add(t);
    }
    // Recurse into ancestors (superclass, interfaces)
    for (Type type : ancestors) {
        if (type instanceof SootClassType) {
            // ancestor is non-parameterized. Recurse only if it matches the base class.
            SootClassType ancestorClass = (SootClassType) type;
            if (base.isAssignableFrom(ancestorClass)) {
                Type[] result = resolveActualTypeArgs(ancestorClass, base);
                if (result != null) {
                    return result;
                }
            }
        }
        if (type instanceof ParameterizedType) {
            // ancestor is parameterized. Recurse only if the raw type matches the base class.
            ParameterizedType parameterizedType = (ParameterizedType) type;
            Type rawType = parameterizedType.getRawType();
            if (rawType instanceof SootClassType) {
                SootClassType rawTypeClass = (SootClassType) rawType;
                if (base.isAssignableFrom(rawTypeClass)) {
                    parameterizedType = resolveParameterizedType(parameterizedType, typeVariables);
                    Type[] result = resolveActualTypeArgs(rawTypeClass, base, parameterizedType.getActualTypeArguments());
                    if (result != null) {
                        return result;
                    }
                }
            }
        }
    }
    // we have a result if we reached the base class.
    return offspring.equals(base) ? actualArgs : null;
}
Also used : SootClassType(org.robovm.compiler.util.generic.SootClassType) HashMap(java.util.HashMap) LinkedList(java.util.LinkedList) ParameterizedType(org.robovm.compiler.util.generic.ParameterizedType) 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) WildcardType(org.robovm.compiler.util.generic.WildcardType) TypeVariable(org.robovm.compiler.util.generic.TypeVariable)

Example 8 with Type

use of org.robovm.compiler.util.generic.Type 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 9 with Type

use of org.robovm.compiler.util.generic.Type in project robovm by robovm.

the class ObjCBlockPlugin method resolveParameterizedType.

/**
     * Loops through all type arguments and replaces type variables with the
     * actually known types.
     */
private static ParameterizedType resolveParameterizedType(ParameterizedType parameterizedType, Map<String, Type> typeVariables) {
    List<Type> resolvedTypes = new LinkedList<Type>();
    for (Type t : parameterizedType.getActualTypeArguments()) {
        if (t instanceof TypeVariable<?>) {
            Type resolvedType = typeVariables.get(((TypeVariable<?>) t).getName());
            if (resolvedType instanceof ParameterizedType) {
                resolvedType = resolveParameterizedType((ParameterizedType) resolvedType, typeVariables);
            }
            resolvedTypes.add(resolvedType != null ? resolvedType : t);
        } else if (t instanceof ParameterizedType) {
            ParameterizedType pType = (ParameterizedType) t;
            resolvedTypes.add(resolveParameterizedType(pType, typeVariables));
        } else {
            resolvedTypes.add(t);
        }
    }
    ListOfTypes types = new ListOfTypes(resolvedTypes.toArray(new Type[resolvedTypes.size()]));
    return new ImplForType(null, parameterizedType.getRawType().toString(), types);
}
Also used : ParameterizedType(org.robovm.compiler.util.generic.ParameterizedType) 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) TypeVariable(org.robovm.compiler.util.generic.TypeVariable) ListOfTypes(org.robovm.compiler.util.generic.ListOfTypes) ImplForType(org.robovm.compiler.util.generic.ImplForType) LinkedList(java.util.LinkedList)

Example 10 with Type

use of org.robovm.compiler.util.generic.Type in project robovm by robovm.

the class ObjCBlockPlugin method getGenericSignature.

private String getGenericSignature(List<Type> genericParamTypes, Type genericReturnType) {
    StringBuilder sb = new StringBuilder();
    sb.append("(");
    for (Type t : genericParamTypes) {
        sb.append(t.toGenericSignature());
    }
    sb.append(")");
    sb.append(genericReturnType.toGenericSignature());
    String s = sb.toString();
    if (s.contains("<")) {
        return s;
    }
    // Not a generic signature.
    return null;
}
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)

Aggregations

SootClassType (org.robovm.compiler.util.generic.SootClassType)11 SootMethodType (org.robovm.compiler.util.generic.SootMethodType)11 SootTypeType (org.robovm.compiler.util.generic.SootTypeType)11 Type (org.robovm.compiler.util.generic.Type)11 BooleanType (soot.BooleanType)11 VoidType (soot.VoidType)11 GenericArrayType (org.robovm.compiler.util.generic.GenericArrayType)10 ImplForType (org.robovm.compiler.util.generic.ImplForType)10 ParameterizedType (org.robovm.compiler.util.generic.ParameterizedType)10 WildcardType (org.robovm.compiler.util.generic.WildcardType)10 ByteType (soot.ByteType)10 CharType (soot.CharType)10 DoubleType (soot.DoubleType)10 FloatType (soot.FloatType)10 IntType (soot.IntType)10 LongType (soot.LongType)10 PrimType (soot.PrimType)10 RefType (soot.RefType)10 ShortType (soot.ShortType)10 MethodVisitor (org.objectweb.asm.MethodVisitor)4