use of soot.SootMethod in project robovm by robovm.
the class ObjCMemberPlugin method getMsgSendSuperMethod.
@SuppressWarnings("unchecked")
private SootMethod getMsgSendSuperMethod(String selectorName, SootMethod method) {
List<Type> paramTypes = new ArrayList<>();
paramTypes.add(org_robovm_objc_ObjCSuper.getType());
paramTypes.add(org_robovm_objc_Selector.getType());
paramTypes.addAll(method.getParameterTypes());
SootMethod m = new SootMethod("$m$super$" + selectorName.replace(':', '$'), paramTypes, method.getReturnType(), STATIC | PRIVATE | NATIVE);
copyAnnotations(method, m, false);
createGenericSignatureForMsgSend(method, m, paramTypes, false);
return m;
}
use of soot.SootMethod in project robovm by robovm.
the class ObjCMemberPlugin method beforeClass.
@Override
public void beforeClass(Config config, Clazz clazz, ModuleBuilder moduleBuilder) {
init(config);
SootClass sootClass = clazz.getSootClass();
boolean extensions = false;
if (!sootClass.isInterface() && (isObjCObject(sootClass) || (extensions = isObjCExtensions(sootClass)))) {
Set<String> selectors = new TreeSet<>();
Set<String> overridables = new HashSet<>();
for (SootMethod method : sootClass.getMethods()) {
if (!"<clinit>".equals(method.getName()) && !"<init>".equals(method.getName())) {
transformMethod(config, clazz, sootClass, method, selectors, overridables, extensions);
}
}
addBindCall(sootClass);
if (!extensions) {
addObjCClassField(sootClass);
}
registerSelectors(sootClass, selectors);
}
}
use of soot.SootMethod in project robovm by robovm.
the class ObjCMemberPlugin method findStrongRefGetter.
private SootMethod findStrongRefGetter(SootClass sootClass, final SootMethod method, boolean extensions) {
AnnotationTag annotation = getAnnotation(method, PROPERTY);
if (annotation == null) {
annotation = getAnnotation(method, IBOUTLET);
}
if (annotation == null) {
annotation = getAnnotation(method, IBOUTLETCOLLECTION);
}
String setterPropName = readStringElem(annotation, "name", "").trim();
if (setterPropName.length() == 0) {
String methodName = method.getName();
if (!methodName.startsWith("set") || methodName.length() == 3) {
throw new CompilerException("Failed to determine the property " + "name from the @Property method " + method + ". Either specify the name explicitly in the @Property " + "annotation or rename the method according to the Java " + "beans property setter method naming convention.");
}
setterPropName = methodName.substring(3);
setterPropName = setterPropName.substring(0, 1).toLowerCase() + setterPropName.substring(1);
}
int paramCount = extensions ? 1 : 0;
Type propType = method.getParameterType(extensions ? 1 : 0);
for (SootMethod m : sootClass.getMethods()) {
if (m != method && method.isStatic() == m.isStatic() && m.getParameterCount() == paramCount && m.getReturnType().equals(propType)) {
AnnotationTag propertyAnno = getAnnotation(m, PROPERTY);
if (propertyAnno != null) {
String getterPropName = readStringElem(propertyAnno, "name", "").trim();
if (getterPropName.length() == 0) {
String methodName = m.getName();
if (!methodName.startsWith("get") || methodName.length() == 3) {
// style getter
continue;
}
getterPropName = methodName.substring(3);
getterPropName = getterPropName.substring(0, 1).toLowerCase() + getterPropName.substring(1);
}
if (setterPropName.equals(getterPropName)) {
return m;
}
}
}
}
throw new CompilerException("Failed to determine the getter method " + "corresponding to the strong ref @Property setter method " + method + ". The getter must either specify the name explicitly in the @Property " + "annotation or be named according to the Java " + "beans property getter method naming convention.");
}
use of soot.SootMethod in project robovm by robovm.
the class TrampolineCompiler method compile.
public void compile(ModuleBuilder mb, Clazz currentClass, Trampoline t, Set<String> dependencies, Set<Triple<String, String, String>> methodDependencies) {
this.mb = mb;
addDependencyIfNeeded(dependencies, currentClass, t);
/*
* Check if the target class exists and is accessible. Also check that
* field accesses and method calls are compatible with the target
* field/method and that the field/method is accessible to the caller.
* If any of the tests fail the weak trampoline function created by the
* ClassCompiler will be overridden with a function which throws an
* appropriate exception.
*/
Function errorFn = new FunctionBuilder(t).linkage(external).build();
if (!checkClassExists(errorFn, t) || !checkClassAccessible(errorFn, t)) {
mb.addFunction(errorFn);
return;
}
if (t instanceof New) {
SootClass target = config.getClazzes().load(t.getTarget()).getSootClass();
if (target.isAbstract() || target.isInterface()) {
call(errorFn, BC_THROW_INSTANTIATION_ERROR, errorFn.getParameterRef(0), mb.getString(t.getTarget().replace('/', '.')));
errorFn.add(new Unreachable());
mb.addFunction(errorFn);
return;
}
String fnName = Symbols.clinitWrapperSymbol(Symbols.allocatorSymbol(t.getTarget()));
alias(t, fnName);
} else if (t instanceof Instanceof) {
if (isArray(t.getTarget())) {
FunctionRef fnRef = createInstanceofArray((Instanceof) t);
alias(t, fnRef.getName());
} else {
String fnName = Symbols.instanceofSymbol(t.getTarget());
alias(t, fnName);
}
} else if (t instanceof Checkcast) {
if (isArray(t.getTarget())) {
FunctionRef fnRef = createCheckcastArray((Checkcast) t);
alias(t, fnRef.getName());
} else {
String fnName = Symbols.checkcastSymbol(t.getTarget());
alias(t, fnName);
}
} else if (t instanceof LdcClass) {
if (isArray(t.getTarget())) {
FunctionRef fnRef = createLdcArray((LdcClass) t);
alias(t, fnRef.getName());
} else {
String fnName = Symbols.ldcExternalSymbol(t.getTarget());
alias(t, fnName);
}
} else if (t instanceof Anewarray) {
FunctionRef fnRef = createAnewarray((Anewarray) t);
alias(t, fnRef.getName());
} else if (t instanceof Multianewarray) {
FunctionRef fnRef = createMultianewarray((Multianewarray) t);
alias(t, fnRef.getName());
} else if (t instanceof FieldAccessor) {
SootField field = resolveField(errorFn, (FieldAccessor) t);
if (field != null) {
dependencies.add(getInternalName(field.getDeclaringClass()));
}
if (field == null || !checkMemberAccessible(errorFn, t, field)) {
mb.addFunction(errorFn);
return;
}
Clazz caller = config.getClazzes().load(t.getCallingClass());
Clazz target = config.getClazzes().load(t.getTarget());
if (!((FieldAccessor) t).isGetter() && field.isFinal() && caller != target) {
// Only the class declaring a final field may write to it.
// (Actually only <init>/<clinit> methods may write to it but we
// don't know which method is accessing the field at this point)
throwIllegalAccessError(errorFn, ATTEMPT_TO_WRITE_TO_FINAL_FIELD, target, field.getName(), caller);
mb.addFunction(errorFn);
return;
}
if (!field.isStatic()) {
createInlinedAccessorForInstanceField((FieldAccessor) t, field);
} else {
createTrampolineAliasForField((FieldAccessor) t, field);
}
} else if (t instanceof Invokeinterface) {
SootMethod rm = resolveInterfaceMethod(errorFn, (Invokeinterface) t);
if (rm != null) {
methodDependencies.add(new ImmutableTriple<String, String, String>(getInternalName(rm.getDeclaringClass()), rm.getName(), getDescriptor(rm)));
}
if (rm == null || !checkMemberAccessible(errorFn, t, rm)) {
mb.addFunction(errorFn);
return;
}
createTrampolineAliasForMethod((Invoke) t, rm);
} else if (t instanceof Invoke) {
SootMethod method = resolveMethod(errorFn, (Invoke) t);
if (method != null) {
methodDependencies.add(new ImmutableTriple<String, String, String>(getInternalName(method.getDeclaringClass()), method.getName(), getDescriptor(method)));
}
if (method == null || !checkMemberAccessible(errorFn, t, method)) {
mb.addFunction(errorFn);
return;
}
if (t instanceof Invokespecial && method.isAbstract()) {
call(errorFn, BC_THROW_ABSTRACT_METHOD_ERROR, errorFn.getParameterRef(0), mb.getString(String.format(NO_SUCH_METHOD_ERROR, method.getDeclaringClass(), method.getName(), getDescriptor(method))));
errorFn.add(new Unreachable());
mb.addFunction(errorFn);
return;
}
createTrampolineAliasForMethod((Invoke) t, method);
}
}
use of soot.SootMethod in project robovm by robovm.
the class AnnotationImplPlugin method generateSlowEqualsMethod.
private void generateSlowEqualsMethod(Clazz clazz, ClassWriter cw) {
String implName = clazz.getInternalName() + IMPL_CLASS_NAME_SUFFIX;
// boolean slowEquals(Object that);
// that is known to be an instance of the same interface but not an instance of our impl class.
MethodVisitor mv = cw.visitMethod(ACC_PROTECTED, "slowEquals", "(Ljava/lang/Object;)Z", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 1);
mv.visitTypeInsn(CHECKCAST, clazz.getInternalName());
mv.visitVarInsn(ASTORE, 1);
Label l1 = new Label();
for (SootMethod method : clazz.getSootClass().getMethods()) {
String fieldName = getFieldName(method);
soot.Type type = method.getReturnType();
mv.visitVarInsn(ALOAD, 0);
mv.visitInsn(DUP);
mv.visitFieldInsn(GETFIELD, implName, fieldName, "Ljava/lang/Object;");
mv.visitVarInsn(ALOAD, 1);
mv.visitMethodInsn(INVOKEINTERFACE, clazz.getInternalName(), method.getName(), "()" + Types.getDescriptor(type));
boxIfNeeded(mv, type);
mv.visitMethodInsn(INVOKESPECIAL, BASE_CLASS, "memberEquals", "(Ljava/lang/Object;Ljava/lang/Object;)Z");
mv.visitJumpInsn(IFEQ, l1);
}
// return true;
mv.visitInsn(ICONST_1);
mv.visitInsn(IRETURN);
// return false
mv.visitLabel(l1);
mv.visitInsn(ICONST_0);
mv.visitInsn(IRETURN);
mv.visitMaxs(0, 0);
mv.visitEnd();
}
Aggregations