use of soot.SootClass 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.SootClass 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();
}
use of soot.SootClass in project robovm by robovm.
the class TrampolineCompiler method resolveMethod.
private SootMethod resolveMethod(SootClass clazz, String name, String desc) {
if (clazz != null && !clazz.isPhantom()) {
SootMethod method = getMethod(clazz, name, desc);
if (method != null) {
return method;
}
if (name.equals("sizeOf") && isStruct(clazz)) {
method = new SootMethod("sizeOf", Collections.EMPTY_LIST, IntType.v(), Modifier.PUBLIC | Modifier.STATIC);
method.setDeclaringClass(clazz);
method.setDeclared(true);
return method;
}
SootClass c = !clazz.isInterface() && clazz.hasSuperclass() ? clazz.getSuperclass() : null;
while (c != null) {
method = getMethod(c, name, desc);
if (method != null) {
return method;
}
c = !c.isInterface() && c.hasSuperclass() ? c.getSuperclass() : null;
}
c = clazz;
while (c != null) {
for (SootClass interfaze : c.getInterfaces()) {
method = resolveInterfaceMethod(interfaze, name, desc);
if (method != null) {
return method;
}
}
c = !c.isInterface() && c.hasSuperclass() ? c.getSuperclass() : null;
}
}
return null;
}
use of soot.SootClass in project robovm by robovm.
the class TrampolineCompiler method resolveInterfaceMethod.
private SootMethod resolveInterfaceMethod(Function f, Invokeinterface t) {
SootClass target = config.getClazzes().load(t.getTarget()).getSootClass();
String name = t.getMethodName();
String desc = t.getMethodDesc();
if (!target.isInterface()) {
throwIncompatibleChangeError(f, EXPECTED_INTERFACE_BUT_FOUND_CLASS, target);
return null;
}
if ("<clinit>".equals(name) || "<init>".equals(name)) {
// This is not part of interface method resolution but we
// need to handle it somehow.
throwNoSuchMethodError(f, t);
return null;
}
SootMethod method = resolveInterfaceMethod(target, name, desc);
if (method == null) {
SootClass javaLangObject = config.getClazzes().load("java/lang/Object").getSootClass();
method = getMethod(javaLangObject, name, desc);
}
if (method == null) {
throwNoSuchMethodError(f, t);
return null;
}
if (method.isStatic()) {
throwIncompatibleChangeError(f, EXPECTED_NON_STATIC_METHOD, target, name, desc);
return null;
}
return method;
}
use of soot.SootClass in project robovm by robovm.
the class MarshalerLookup method findMarshalers.
public Marshaler findMarshalers(MarshalSite marshalSite) {
soot.Type type = marshalSite.getType();
SootClass sc = null;
if (type instanceof RefType) {
sc = ((RefType) type).getSootClass();
} else if (type instanceof ArrayType && ((ArrayType) type).baseType instanceof RefType) {
sc = ((RefType) ((ArrayType) type).baseType).getSootClass();
}
List<Marshaler> result = new ArrayList<>();
Set<String> visited = new HashSet<>();
Set<String> seen = new HashSet<>();
if (sc != null) {
findMarshalers(sc, result, visited, seen, false);
}
findMarshalers(marshalSite.method.getDeclaringClass(), result, visited, seen, searchBuiltins);
for (Marshaler marshaler : result) {
if (marshaler.canMarshal(marshalSite)) {
return marshaler;
}
}
return null;
}
Aggregations