use of org.robovm.compiler.llvm.Function in project robovm by robovm.
the class StructMemberMethodCompiler method structMember.
private Function structMember(ModuleBuilder moduleBuilder, SootMethod method) {
Function function = createMethodFunction(method);
moduleBuilder.addFunction(function);
// Get the value of the handle field in the Struct base class and cast it to a <structType>*
Variable handleI64 = function.newVariable(I64);
function.add(new Load(handleI64, getFieldPtr(function, function.getParameterRef(1), offsetof(new StructureType(DATA_OBJECT, new StructureType(I64)), 1, 0), I64)));
Variable handlePtr = function.newVariable(new PointerType(structType));
function.add(new Inttoptr(handlePtr, handleI64.ref(), handlePtr.getType()));
// Add 1 since the first type in structType is the superclass type or {}.
int offset = getStructMemberOffset(method) + 1;
Type memberType = getStructMemberType(method);
Variable memberPtr = function.newVariable(new PointerType(memberType));
if (memberType != structType.getTypeAt(offset)) {
// Several @StructMembers of different types have this offset (union)
Variable tmp = function.newVariable(new PointerType(structType.getTypeAt(offset)));
function.add(new Getelementptr(tmp, handlePtr.ref(), 0, offset));
function.add(new Bitcast(memberPtr, tmp.ref(), memberPtr.getType()));
} else {
function.add(new Getelementptr(memberPtr, handlePtr.ref(), 0, offset));
}
VariableRef env = function.getParameterRef(0);
if (method.getParameterCount() == 0) {
// Getter
Value result = loadValueForGetter(method, function, memberType, memberPtr.ref(), function.getParameterRef(0), true, MarshalerFlags.CALL_TYPE_STRUCT_MEMBER);
function.add(new Ret(result));
} else {
// Setter
// 'env' is parameter 0, 'this' is at 1, the value we're interested in is at index 2
Value value = function.getParameterRef(2);
storeValueForSetter(method, function, memberType, memberPtr.ref(), env, value, MarshalerFlags.CALL_TYPE_STRUCT_MEMBER);
if (method.getReturnType().equals(VoidType.v())) {
function.add(new Ret());
} else {
function.add(new Ret(function.getParameterRef(1)));
}
}
return function;
}
use of org.robovm.compiler.llvm.Function in project robovm by robovm.
the class StructMemberMethodCompiler method structSizeOf.
private Function structSizeOf(ModuleBuilder moduleBuilder, SootMethod method) {
Function fn = createMethodFunction(method);
moduleBuilder.addFunction(fn);
fn.add(new Ret(sizeof(structType)));
return fn;
}
use of org.robovm.compiler.llvm.Function 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 org.robovm.compiler.llvm.Function 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 org.robovm.compiler.llvm.Function in project robovm by robovm.
the class TrampolineCompiler method alias.
private void alias(Trampoline t, String fnName) {
FunctionRef aliasee = new FunctionRef(fnName, t.getFunctionType());
if (!mb.hasSymbol(fnName)) {
mb.addFunctionDeclaration(new FunctionDeclaration(aliasee));
}
Function fn = new FunctionBuilder(t).linkage(aliasLinkage()).attribs(shouldInline(), optsize).build();
Value result = call(fn, aliasee, fn.getParameterRefs());
fn.add(new Ret(result));
mb.addFunction(fn);
}
Aggregations