use of org.robovm.compiler.trampoline.LdcClass in project robovm by robovm.
the class MethodCompiler method immediate.
private Value immediate(Unit unit, Immediate v) {
// v is either a soot.Local or a soot.jimple.Constant
if (v instanceof soot.Local) {
Local local = (Local) v;
Type type = getLocalType(v.getType());
VariableRef var = new VariableRef(local.getName(), new PointerType(type));
Variable tmp = function.newVariable(type);
function.add(new Load(tmp, var, !sootMethod.getActiveBody().getTraps().isEmpty())).attach(unit);
return new VariableRef(tmp);
} else if (v instanceof soot.jimple.IntConstant) {
return new IntegerConstant(((soot.jimple.IntConstant) v).value);
} else if (v instanceof soot.jimple.LongConstant) {
return new IntegerConstant(((soot.jimple.LongConstant) v).value);
} else if (v instanceof soot.jimple.FloatConstant) {
return new FloatingPointConstant(((soot.jimple.FloatConstant) v).value);
} else if (v instanceof soot.jimple.DoubleConstant) {
return new FloatingPointConstant(((soot.jimple.DoubleConstant) v).value);
} else if (v instanceof soot.jimple.NullConstant) {
return new NullConstant(OBJECT_PTR);
} else if (v instanceof soot.jimple.StringConstant) {
String s = ((soot.jimple.StringConstant) v).value;
return call(unit, ldcString(s), env);
} else if (v instanceof soot.jimple.ClassConstant) {
// ClassConstant is either the internal name of a class or the descriptor of an array
String targetClassName = ((soot.jimple.ClassConstant) v).getValue();
if (isArray(targetClassName) && isPrimitiveComponentType(targetClassName)) {
String primitiveDesc = targetClassName.substring(1);
Variable result = function.newVariable(OBJECT_PTR);
function.add(new Load(result, new ConstantBitcast(new GlobalRef("array_" + primitiveDesc, CLASS_PTR), new PointerType(OBJECT_PTR)))).attach(unit);
return result.ref();
} else {
FunctionRef fn = null;
if (targetClassName.equals(this.className)) {
fn = FunctionBuilder.ldcInternal(sootMethod.getDeclaringClass()).ref();
} else {
Trampoline trampoline = new LdcClass(className, ((soot.jimple.ClassConstant) v).getValue());
trampolines.add(trampoline);
fn = trampoline.getFunctionRef();
}
return call(unit, fn, env);
}
}
throw new IllegalArgumentException("Unknown Immediate type: " + v.getClass());
}
use of org.robovm.compiler.trampoline.LdcClass in project robovm by robovm.
the class BroMethodCompiler method ldcClass.
protected Value ldcClass(Function fn, String name, Value env) {
if (isArray(name) && isPrimitiveBaseType(name)) {
String primitiveDesc = name.substring(name.length() - 1);
Variable result = fn.newVariable(OBJECT_PTR);
fn.add(new Load(result, new ConstantBitcast(new GlobalRef("array_" + primitiveDesc, CLASS_PTR), new PointerType(OBJECT_PTR))));
return result.ref();
} else {
FunctionRef ldcClassFn = null;
if (name.equals(this.className)) {
ldcClassFn = FunctionBuilder.ldcInternal(this.className).ref();
} else {
Trampoline trampoline = new LdcClass(this.className, name);
trampolines.add(trampoline);
ldcClassFn = trampoline.getFunctionRef();
}
return call(fn, ldcClassFn, env);
}
}
use of org.robovm.compiler.trampoline.LdcClass 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);
}
}
Aggregations