use of soot.PrimType in project soot by Sable.
the class ReflectiveCallsInliner method insertCastOrUnboxingCode.
private void insertCastOrUnboxingCode(Local lhs, Local rhs, Chain<Unit> newUnits) {
// if assigning to a reference type then there's nothing to do
if (lhs.getType() instanceof PrimType) {
if ((rhs.getType() instanceof PrimType)) {
// insert cast
newUnits.add(Jimple.v().newAssignStmt(lhs, Jimple.v().newCastExpr(rhs, lhs.getType())));
} else {
// reference type in rhs; insert unboxing code
RefType boxedType = (RefType) rhs.getType();
SootMethodRef ref = Scene.v().makeMethodRef(boxedType.getSootClass(), lhs.getType().toString() + "Value", Collections.<Type>emptyList(), lhs.getType(), false);
newUnits.add(Jimple.v().newAssignStmt(lhs, Jimple.v().newVirtualInvokeExpr(rhs, ref)));
}
}
}
use of soot.PrimType 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 soot.PrimType 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 soot.PrimType in project robovm by robovm.
the class AnnotationImplPlugin method generateMemberFieldsAndAccessorMethods.
private void generateMemberFieldsAndAccessorMethods(Clazz clazz, ClassWriter cw) throws IOException {
String implName = clazz.getInternalName() + IMPL_CLASS_NAME_SUFFIX;
SootClass sootClass = clazz.getSootClass();
List<SootMethod> methods = sootClass.getMethods();
for (SootMethod method : methods) {
String fieldName = getFieldName(method);
soot.Type type = method.getReturnType();
String typeDesc = Types.getDescriptor(type);
// Add the field. Values are always stored as Object. If there was
// an error in the annotation in the class file this will be an
// Exception which will get thrown by the accessor method.
cw.visitField(ACC_PRIVATE, fieldName, "Ljava/lang/Object;", null, null).visitEnd();
// Add the public accessor method
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, method.getName(), Types.getDescriptor(method), null, null);
mv.visitCode();
// v = validate(<field>, <memberName>)
mv.visitVarInsn(ALOAD, 0);
mv.visitInsn(DUP);
mv.visitFieldInsn(GETFIELD, implName, fieldName, "Ljava/lang/Object;");
mv.visitLdcInsn(method.getName());
mv.visitMethodInsn(INVOKESPECIAL, BASE_CLASS, "validate", "(Ljava/lang/Object;Ljava/lang/String;)Ljava/lang/Object;");
// return v (unboxed if needed)
int retOp = 0;
switch(typeDesc.charAt(0)) {
case 'Z':
case 'B':
case 'S':
case 'C':
case 'I':
retOp = IRETURN;
break;
case 'J':
retOp = LRETURN;
break;
case 'F':
retOp = FRETURN;
break;
case 'D':
retOp = DRETURN;
break;
default:
retOp = ARETURN;
break;
}
unboxIfNeeded(mv, type);
if (!(type instanceof PrimType)) {
// Reference type
mv.visitTypeInsn(CHECKCAST, Types.getInternalName(type));
}
mv.visitInsn(retOp);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
}
use of soot.PrimType in project robovm by robovm.
the class AnnotationImplPlugin method generateSetDefaultsMethod.
private void generateSetDefaultsMethod(Clazz clazz, ClassWriter cw) {
String implName = clazz.getInternalName() + IMPL_CLASS_NAME_SUFFIX;
SootClass sootClass = clazz.getSootClass();
List<SootMethod> methods = sootClass.getMethods();
// Generate the $setDefaults() method which is called from the constructor
// to set any default values
MethodVisitor mv = cw.visitMethod(ACC_PRIVATE, "$setDefaults", "()V", null, null);
mv.visitCode();
for (SootMethod method : methods) {
AnnotationDefaultTag defTag = (AnnotationDefaultTag) method.getTag(AnnotationDefaultTag.class.getSimpleName());
String fieldName = getFieldName(method);
if (defTag == null) {
// No default value. Set field to super.NO_VALUE.
mv.visitVarInsn(ALOAD, 0);
mv.visitFieldInsn(GETSTATIC, BASE_CLASS, "NO_VALUE", "Ljava/lang/Object;");
mv.visitFieldInsn(PUTFIELD, implName, fieldName, "Ljava/lang/Object;");
} else {
soot.Type type = method.getReturnType();
String typeDesc = Types.getDescriptor(type);
Object v = null;
if (type instanceof PrimType) {
switch(typeDesc.charAt(0)) {
case 'Z':
case 'B':
case 'S':
case 'C':
case 'I':
v = ((AnnotationIntElem) defTag.getDefaultVal()).getValue();
break;
case 'J':
v = ((AnnotationLongElem) defTag.getDefaultVal()).getValue();
break;
case 'F':
v = ((AnnotationFloatElem) defTag.getDefaultVal()).getValue();
break;
case 'D':
v = ((AnnotationDoubleElem) defTag.getDefaultVal()).getValue();
break;
}
} else if ("Ljava/lang/Class;".equals(typeDesc)) {
v = Type.getType(((AnnotationClassElem) defTag.getDefaultVal()).getDesc());
if (((Type) v).getDescriptor().length() != 1) {
// Only use a simple LDC for primitive classes (e.g. byte.class).
// Other classes may not be available at runtime. By falling back
// to Method.getDefaultValue() below we will get the proper
// exception at runtime.
v = null;
}
} else if ("Ljava/lang/String;".equals(typeDesc)) {
v = ((AnnotationStringElem) defTag.getDefaultVal()).getValue();
}
if (v != null) {
mv.visitVarInsn(ALOAD, 0);
if (v instanceof Type && ((Type) v).getDescriptor().length() == 1) {
// LDC of primitive type class such as byte.class
switch(((Type) v).getDescriptor().charAt(0)) {
case 'V':
mv.visitFieldInsn(GETSTATIC, "java/lang/Void", "TYPE", "Ljava/lang/Class;");
break;
case 'Z':
mv.visitFieldInsn(GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;");
break;
case 'B':
mv.visitFieldInsn(GETSTATIC, "java/lang/Byte", "TYPE", "Ljava/lang/Class;");
break;
case 'S':
mv.visitFieldInsn(GETSTATIC, "java/lang/Short", "TYPE", "Ljava/lang/Class;");
break;
case 'C':
mv.visitFieldInsn(GETSTATIC, "java/lang/Character", "TYPE", "Ljava/lang/Class;");
break;
case 'I':
mv.visitFieldInsn(GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;");
break;
case 'J':
mv.visitFieldInsn(GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;");
break;
case 'F':
mv.visitFieldInsn(GETSTATIC, "java/lang/Float", "TYPE", "Ljava/lang/Class;");
break;
case 'D':
mv.visitFieldInsn(GETSTATIC, "java/lang/Double", "TYPE", "Ljava/lang/Class;");
break;
}
} else {
mv.visitLdcInsn(v);
}
boxIfNeeded(mv, type);
mv.visitFieldInsn(PUTFIELD, implName, fieldName, "Ljava/lang/Object;");
} else {
// Must be class, enum, array type or annotation. Fall back to super.getDefaultValue(<memberName>).
mv.visitVarInsn(ALOAD, 0);
mv.visitInsn(DUP);
mv.visitLdcInsn(method.getName());
mv.visitMethodInsn(INVOKESPECIAL, BASE_CLASS, "getDefaultValue", "(Ljava/lang/String;)Ljava/lang/Object;");
mv.visitFieldInsn(PUTFIELD, implName, fieldName, "Ljava/lang/Object;");
}
}
}
mv.visitInsn(RETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
Aggregations