use of soot.SootField in project robovm by robovm.
the class Types method getFields.
public static List<SootField> getFields(final OS os, final Arch arch, SootClass clazz, boolean ztatic) {
List<SootField> l = new ArrayList<SootField>();
for (SootField f : clazz.getFields()) {
if (ztatic == f.isStatic()) {
l.add(f);
}
}
// Sort the fields. references, volatile long, double, long, float, int, char, short, boolean, byte.
// Fields of same type are sorted by name.
Collections.sort(l, new Comparator<SootField>() {
@Override
public int compare(SootField o1, SootField o2) {
soot.Type t1 = o1.getType();
soot.Type t2 = o2.getType();
if (t1 instanceof RefLikeType) {
if (!(t2 instanceof RefLikeType)) {
return -1;
}
}
if (t2 instanceof RefLikeType) {
if (!(t1 instanceof RefLikeType)) {
return 1;
}
}
// Compare alignment. Higher first.
int align1 = getFieldAlignment(os, arch, o1);
int align2 = getFieldAlignment(os, arch, o2);
int c = new Integer(align2).compareTo(align1);
if (c == 0) {
// Compare size. Larger first.
int size1 = getFieldSize(arch, o1);
int size2 = getFieldSize(arch, o2);
c = new Integer(size2).compareTo(size1);
if (c == 0) {
// Compare type name.
c = t1.getClass().getSimpleName().compareTo(t2.getClass().getSimpleName());
if (c == 0) {
// Compare name.
c = o1.getName().compareTo(o2.getName());
}
}
}
return c;
}
});
return l;
}
use of soot.SootField in project robovm by robovm.
the class MethodCompiler method canAccessDirectly.
// private Value callOrInvoke(Unit unit, Value fn, Value ... args) {
// Variable result = null;
// Type returnType = ((FunctionType) fn.getType()).getReturnType();
// if (returnType != VOID) {
// result = this.function.newVariable(returnType);
// }
// List<Trap> traps = getTrapsAt(unit);
// if (!traps.isEmpty()) {
// Label label = new Label();
// BasicBlockRef to = function.newBasicBlockRef(label);
// BasicBlockRef unwind = function.newBasicBlockRef(new Label(traps));
// function.add(new Invoke(result, fn, to, unwind, args));
// function.newBasicBlock(label);
// recordedTraps.add(traps);
// } else {
// function.add(new Call(result, fn, args));
// }
// return result == null ? null : result.ref();
// }
private boolean canAccessDirectly(FieldRef ref) {
SootClass sootClass = this.sootMethod.getDeclaringClass();
SootFieldRef fieldRef = ref.getFieldRef();
if (!fieldRef.declaringClass().equals(sootClass)) {
return false;
}
try {
SootField field = sootClass.getField(fieldRef.name(), fieldRef.type());
/*
* The field exists.
*/
if (field.isStatic()) {
// If not we want an exception to be thrown so we need a trampoline.
return ref instanceof StaticFieldRef;
}
// If not we want an exception to be thrown so we need a trampoline.
return ref instanceof InstanceFieldRef;
} catch (RuntimeException e) {
// isn't declared in the class.
return false;
}
}
use of soot.SootField 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.SootField in project robovm by robovm.
the class TrampolineCompiler method createInlinedAccessorForInstanceField.
private void createInlinedAccessorForInstanceField(FieldAccessor t, SootField field) {
Function fn = new FunctionBuilder(t).linkage(aliasLinkage()).attribs(shouldInline(), optsize).build();
List<SootField> classFields = Collections.emptyList();
StructureType classType = new StructureType();
List<SootField> instanceFields = getInstanceFields(config.getOs(), config.getArch(), field.getDeclaringClass());
StructureType instanceType = getInstanceType(config.getOs(), config.getArch(), field.getDeclaringClass());
if (t.isGetter()) {
ClassCompiler.createFieldGetter(fn, field, classFields, classType, instanceFields, instanceType);
} else {
ClassCompiler.createFieldSetter(fn, field, classFields, classType, instanceFields, instanceType);
}
mb.addFunction(fn);
}
use of soot.SootField in project robovm by robovm.
the class Types method getInstanceType0.
private static PackedStructureType getInstanceType0(OS os, Arch arch, SootClass clazz, int subClassAlignment, int[] superSize) {
List<Type> types = new ArrayList<Type>();
List<SootField> fields = getInstanceFields(os, arch, clazz);
int superAlignment = 1;
if (!fields.isEmpty()) {
// Pad the super type so that the first field is aligned properly
SootField field = fields.get(0);
superAlignment = getFieldAlignment(os, arch, field);
}
if (clazz.hasSuperclass()) {
types.add(getInstanceType0(os, arch, clazz.getSuperclass(), superAlignment, superSize));
}
int offset = superSize[0];
for (SootField field : fields) {
int falign = getFieldAlignment(os, arch, field);
int padding = (offset & (falign - 1)) != 0 ? (falign - (offset & (falign - 1))) : 0;
types.add(padType(getType(field.getType()), padding));
offset += padding + getFieldSize(arch, field);
}
int padding = (offset & (subClassAlignment - 1)) != 0 ? (subClassAlignment - (offset & (subClassAlignment - 1))) : 0;
for (int i = 0; i < padding; i++) {
types.add(I8);
offset++;
}
superSize[0] = offset;
return new PackedStructureType(types.toArray(new Type[types.size()]));
}
Aggregations