Search in sources :

Example 1 with SootTypeType

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

the class ObjCBlockPlugin method resolveTargetMethodSignature.

protected static Type[] resolveTargetMethodSignature(SootMethod blockMethod, SootMethod targetMethod, Type blockParamType) {
    if (targetMethod.getTag("SignatureTag") == null) {
        // Not a generic method.
        Type[] result = new Type[targetMethod.getParameterCount() + 1];
        result[0] = new SootTypeType(targetMethod.getReturnType());
        for (int i = 1; i < result.length; i++) {
            result[i] = new SootTypeType(targetMethod.getParameterType(i - 1));
        }
        return result;
    }
    SootClassType base = new SootClassType(targetMethod.getDeclaringClass());
    TypeVariable<?>[] typeParameters = base.getTypeParameters();
    SootClassType offspring = null;
    Type[] actualArgs = null;
    if (blockParamType instanceof SootClassType) {
        offspring = (SootClassType) blockParamType;
        actualArgs = new Type[0];
    } else if (blockParamType instanceof ParameterizedType) {
        offspring = (SootClassType) ((ParameterizedType) blockParamType).getRawType();
        actualArgs = ((ParameterizedType) blockParamType).getActualTypeArguments();
    }
    Type[] resolvedArgs = resolveActualTypeArgs(offspring, base, actualArgs);
    Type[] result = new Type[targetMethod.getParameterCount() + 1];
    SootMethodType targetMethodType = new SootMethodType(targetMethod);
    result[0] = resolveMethodType(blockMethod, -1, targetMethodType.getGenericReturnType(), resolvedArgs, typeParameters);
    Type[] genericParameterTypes = targetMethodType.getGenericParameterTypes();
    for (int i = 1; i < result.length; i++) {
        result[i] = resolveMethodType(blockMethod, i - 1, genericParameterTypes[i - 1], resolvedArgs, typeParameters);
    }
    return result;
}
Also used : ParameterizedType(org.robovm.compiler.util.generic.ParameterizedType) SootClassType(org.robovm.compiler.util.generic.SootClassType) 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) TypeVariable(org.robovm.compiler.util.generic.TypeVariable) SootMethodType(org.robovm.compiler.util.generic.SootMethodType)

Example 2 with SootTypeType

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

the class ObjCBlockPlugin method resolveMethodType.

/**
     * 
     */
private static Type resolveMethodType(SootMethod blockMethod, int paramIndex, Type t, Type[] resolvedArgs, TypeVariable<?>[] typeParameters) {
    if (t instanceof SootClassType) {
        return t;
    }
    if (t instanceof SootTypeType) {
        return t;
    }
    if (t instanceof TypeVariable) {
        int idx = indexOf(((TypeVariable<?>) t).getName(), typeParameters);
        if (idx != -1) {
            Type u = resolvedArgs[idx];
            if (u instanceof TypeVariable) {
                if (((TypeVariable<?>) t).getName().equals(((TypeVariable<?>) u).getName())) {
                    return resolveMethodType(blockMethod, paramIndex, ((TypeVariable<?>) t).getBounds()[0], resolvedArgs, typeParameters);
                }
            }
            return resolveMethodType(blockMethod, paramIndex, resolvedArgs[idx], resolvedArgs, typeParameters);
        }
        throw new CompilerException("Unresolved type variable " + t + " in " + (paramIndex == -1 ? "return type" : "parameter " + (paramIndex + 1)) + " of @Block method " + blockMethod);
    }
    if (t instanceof WildcardType) {
        Type[] upperBounds = ((WildcardType) t).getUpperBounds();
        return resolveMethodType(blockMethod, paramIndex, upperBounds[0], resolvedArgs, typeParameters);
    }
    if (t instanceof ParameterizedType) {
        ImplForType pType = (ImplForType) t;
        ListOfTypes types = new ListOfTypes(pType.getActualTypeArguments().length);
        for (Type arg : pType.getActualTypeArguments()) {
            types.add(resolveMethodType(blockMethod, paramIndex, arg, resolvedArgs, typeParameters));
        }
        return new ImplForType((ImplForType) pType.getOwnerType(), pType.getRawType().getSootClass().getName(), types);
    }
    if (t instanceof GenericArrayType) {
        Type componentType = resolveMethodType(blockMethod, paramIndex, ((GenericArrayType) t).getGenericComponentType(), resolvedArgs, typeParameters);
        return new ImplForArray(componentType);
    }
    throw new CompilerException("Unresolved type " + t + " in " + (paramIndex == -1 ? "return type" : "parameter " + (paramIndex + 1)) + " of @Block method " + blockMethod);
}
Also used : SootClassType(org.robovm.compiler.util.generic.SootClassType) GenericArrayType(org.robovm.compiler.util.generic.GenericArrayType) ParameterizedType(org.robovm.compiler.util.generic.ParameterizedType) ImplForArray(org.robovm.compiler.util.generic.ImplForArray) SootTypeType(org.robovm.compiler.util.generic.SootTypeType) 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) CompilerException(org.robovm.compiler.CompilerException) ListOfTypes(org.robovm.compiler.util.generic.ListOfTypes) ImplForType(org.robovm.compiler.util.generic.ImplForType)

Example 3 with SootTypeType

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

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

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

the class ObjCBlockPluginTest method setup.

@Before
public void setup() {
    BOOLEAN = new SootTypeType(BooleanType.v());
    VOID = new SootTypeType(VoidType.v());
}
Also used : SootTypeType(org.robovm.compiler.util.generic.SootTypeType) Before(org.junit.Before)

Aggregations

SootTypeType (org.robovm.compiler.util.generic.SootTypeType)5 GenericArrayType (org.robovm.compiler.util.generic.GenericArrayType)4 ImplForType (org.robovm.compiler.util.generic.ImplForType)4 ParameterizedType (org.robovm.compiler.util.generic.ParameterizedType)4 SootClassType (org.robovm.compiler.util.generic.SootClassType)4 SootMethodType (org.robovm.compiler.util.generic.SootMethodType)4 Type (org.robovm.compiler.util.generic.Type)4 WildcardType (org.robovm.compiler.util.generic.WildcardType)4 BooleanType (soot.BooleanType)4 ByteType (soot.ByteType)4 CharType (soot.CharType)4 DoubleType (soot.DoubleType)4 FloatType (soot.FloatType)4 IntType (soot.IntType)4 LongType (soot.LongType)4 PrimType (soot.PrimType)4 RefType (soot.RefType)4 ShortType (soot.ShortType)4 VoidType (soot.VoidType)4 ArrayList (java.util.ArrayList)2