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;
}
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);
}
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();
}
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();
}
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());
}
Aggregations