use of org.robovm.compiler.llvm.StructureType in project robovm by robovm.
the class BroMethodCompiler method loadValueForGetter.
protected Value loadValueForGetter(SootMethod method, Function fn, Type memberType, Value memberPtr, Value env, boolean dereference, long flags) {
soot.Type type = method.getReturnType();
Value result = null;
if (memberType instanceof StructureType) {
// The member is a child struct contained in the current struct
result = memberPtr;
} else if (memberType instanceof ArrayType) {
// The member is an array contained in the current struct
result = memberPtr;
} else if (dereference) {
Variable tmp = fn.newVariable(memberType);
fn.add(new Load(tmp, memberPtr));
result = tmp.ref();
} else {
// Do not dereference the pointer but use it as is. This is needed for
// global values such as _dispatch_main_q which is a struct and not a
// pointer which we should load. We want the address of the struct.
Variable tmp = fn.newVariable(memberType);
fn.add(new Bitcast(tmp, memberPtr, tmp.getType()));
result = tmp.ref();
}
if (needsMarshaler(type)) {
MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(new MarshalSite(method));
String targetClassName = getInternalName(type);
if (memberType instanceof PrimitiveType) {
// Value type wrapping a primitive value (e.g. Enum, Integer and Bits)
result = marshalNativeToValueObject(fn, marshalerMethod, env, targetClassName, result, flags);
} else {
if (memberType instanceof ArrayType) {
// Array
result = marshalNativeToArray(fn, marshalerMethod, env, targetClassName, result, flags, getArrayDimensions(method));
} else {
result = marshalNativeToObject(fn, marshalerMethod, null, env, targetClassName, result, flags);
}
}
} else {
result = marshalNativeToPrimitive(fn, method, result);
}
return result;
}
use of org.robovm.compiler.llvm.StructureType in project robovm by robovm.
the class BroMethodCompiler method getParameterType.
private Type getParameterType(String anno, SootMethod method, int i) {
soot.Type sootType = method.getParameterType(i);
if (hasPointerAnnotation(method, i)) {
if (!sootType.equals(LongType.v())) {
throw new IllegalArgumentException("Parameter " + (i + 1) + " of " + anno + " annotated method " + method + " must be of type long when annotated with @Pointer.");
}
return I8_PTR;
}
if (hasMachineSizedFloatAnnotation(method, i)) {
if (!sootType.equals(DoubleType.v()) && !sootType.equals(FloatType.v())) {
throw new IllegalArgumentException("Parameter " + (i + 1) + " of " + anno + " annotated method " + method + " must be of type float or double when annotated with @MachineSizedFloat.");
}
return config.getArch().is32Bit() ? FLOAT : DOUBLE;
}
if (hasMachineSizedSIntAnnotation(method, i) || hasMachineSizedUIntAnnotation(method, i)) {
if (!sootType.equals(LongType.v())) {
throw new IllegalArgumentException("Parameter " + (i + 1) + " of " + anno + " annotated method " + method + " must be of type long when annotated with " + "@MachineSizedSInt or @MachineSizedUInt");
}
return config.getArch().is32Bit() ? I32 : I64;
}
if (hasStructRetAnnotation(method, i)) {
if (i > 0) {
throw new IllegalArgumentException("Parameter " + (i + 1) + " of " + anno + " annotated method " + method + " cannot be annotated with @StructRet. Only the first" + " parameter may have this annotation.");
}
if (!isStruct(sootType)) {
throw new IllegalArgumentException("Parameter " + (i + 1) + " of " + anno + " annotated method " + method + " must be a sub class of Struct when annotated with @StructRet.");
}
// @StructRet implies pass by reference
return new PointerType(getStructType(sootType));
}
if (isStruct(sootType)) {
StructureType structType = getStructType(sootType);
if (hasByValAnnotation(method, i)) {
return getStructType(sootType);
}
return new PointerType(structType);
} else if (isNativeObject(sootType)) {
// NativeObjects are always passed by reference.
return I8_PTR;
} else if (sootType instanceof PrimType) {
return getType(sootType);
}
MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(new MarshalSite(method, i));
if (marshalerMethod instanceof ValueMarshalerMethod) {
return ((ValueMarshalerMethod) marshalerMethod).getNativeType(config.getArch());
} else {
return I8_PTR;
}
}
use of org.robovm.compiler.llvm.StructureType in project robovm by robovm.
the class BroMethodCompiler method getStructType.
private StructureType getStructType(SootClass clazz, boolean checkEmpty) {
int n = 0;
for (SootMethod method : clazz.getMethods()) {
n = Math.max(getStructMemberOffset(method) + 1, n);
}
Type[] result = new Type[n + 1];
StructureType superType = null;
if (clazz.hasSuperclass()) {
SootClass superclass = clazz.getSuperclass();
if (!superclass.getName().equals("org.robovm.rt.bro.Struct")) {
superType = getStructType(superclass, false);
}
}
result[0] = superType != null ? superType : new StructureType();
for (SootMethod method : clazz.getMethods()) {
int offset = getStructMemberOffset(method);
if (offset != -1) {
if (!method.isNative() && !method.isStatic()) {
throw new IllegalArgumentException("@StructMember annotated method " + method + " must be native and not static");
}
Type type = null;
if (method.getParameterCount() == 0) {
soot.Type sootType = method.getReturnType();
// Possibly a getter
if (hasPointerAnnotation(method) && !sootType.equals(LongType.v())) {
throw new IllegalArgumentException("@StructMember(" + offset + ") annotated getter " + method + " must be of type long when annotated with @Pointer");
}
if (hasMachineSizedFloatAnnotation(method) && !sootType.equals(DoubleType.v()) && !sootType.equals(FloatType.v())) {
throw new IllegalArgumentException("@StructMember(" + offset + ") annotated getter " + method + " must be of type float or double when annotated with @MachineSizedFloat");
}
if ((hasMachineSizedSIntAnnotation(method) || hasMachineSizedUIntAnnotation(method)) && !sootType.equals(LongType.v())) {
throw new IllegalArgumentException("@StructMember(" + offset + ") annotated getter " + method + " must be of type long when annotated with @MachineSizedSInt or @MachineSizedUInt");
}
if (sootType instanceof soot.ArrayType && !hasArrayAnnotation(method)) {
throw new IllegalArgumentException("@Array annotation expected on struct member getter " + method);
}
} else if (method.getParameterCount() == 1) {
soot.Type sootType = method.getParameterType(0);
if (hasPointerAnnotation(method, 0) && !sootType.equals(LongType.v())) {
throw new IllegalArgumentException("@StructMember(" + offset + ") annotated setter " + method + " must be of type long when annotated with @Pointer");
}
if (hasMachineSizedFloatAnnotation(method, 0) && !sootType.equals(DoubleType.v()) && !sootType.equals(FloatType.v())) {
throw new IllegalArgumentException("@StructMember(" + offset + ") annotated setter " + method + " must be of type float or double when annotated with @MachineSizedFloat");
}
if ((hasMachineSizedSIntAnnotation(method, 0) || hasMachineSizedUIntAnnotation(method)) && !sootType.equals(LongType.v())) {
throw new IllegalArgumentException("@StructMember(" + offset + ") annotated setter " + method + " must be of type long when annotated with @MachineSizedSInt or @MachineSizedUInt");
}
if (sootType instanceof soot.ArrayType && !hasArrayAnnotation(method, 0)) {
throw new IllegalArgumentException("@Array annotation expected on first parameter of struct member setter " + method);
}
soot.Type retType = method.getReturnType();
// The return type of the setter must be void or this
if (!retType.equals(VoidType.v()) && !(retType instanceof RefType && ((RefType) retType).getSootClass().equals(clazz))) {
throw new IllegalArgumentException("Setter " + method + " for " + "@StructMember(" + offset + ") " + " must either return nothing or return a " + clazz);
}
} else {
throw new IllegalArgumentException("@StructMember annotated method " + method + " has too many parameters");
}
type = getStructMemberType(method);
int index = offset + 1;
if (result[index] == null) {
result[index] = type;
} else if (type != result[index]) {
// Two members mapped to the same offset (union). Pick
// the type with the largest alignment and pad with bytes
// up to the largest size.
result[index] = mergeStructMemberTypes(config.getDataLayout(), type, result[index]);
}
}
}
for (int i = 1; i < result.length; i++) {
if (result[i] == null) {
throw new IllegalArgumentException("No @StructMember(" + i + ") defined in class " + clazz);
}
}
if (!clazz.isAbstract() && checkEmpty && n == 0 && superType == null) {
throw new IllegalArgumentException("Struct class " + clazz + " has no @StructMember annotated methods");
}
return new StructureType(result);
}
use of org.robovm.compiler.llvm.StructureType in project robovm by robovm.
the class BroMethodCompiler method storeValueForSetter.
protected void storeValueForSetter(SootMethod method, Function function, Type memberType, Value memberPtr, Value env, Value value, long flags) {
soot.Type type = method.getParameterType(0);
if (needsMarshaler(type)) {
MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(new MarshalSite(method, 0));
if (memberType instanceof PrimitiveType) {
value = marshalValueObjectToNative(function, marshalerMethod, memberType, env, value, flags);
} else {
if (memberType instanceof StructureType || memberType instanceof ArrayType) {
// The parameter must not be null. We assume that Structs
// never have a NULL handle so we just check that the Java
// Object isn't null.
call(function, CHECK_NULL, env, value);
}
if (memberType instanceof ArrayType) {
// Array
marshalArrayToNative(function, marshalerMethod, env, value, memberPtr, flags, getArrayDimensions(method, 0));
value = null;
} else {
value = marshalObjectToNative(function, marshalerMethod, null, memberType, env, value, flags);
}
}
} else {
value = marshalPrimitiveToNative(function, method, 0, value);
}
if (value != null) {
function.add(new Store(value, memberPtr));
}
}
use of org.robovm.compiler.llvm.StructureType in project robovm by robovm.
the class BroMethodCompiler method marshalNativeToObject.
protected Value marshalNativeToObject(Function fn, MarshalerMethod marshalerMethod, MarshaledArg marshaledArg, Value env, String valueClassName, Value nativeValue, long flags) {
if (nativeValue.getType() instanceof StructureType) {
nativeValue = createStackCopy(fn, nativeValue);
}
Invokestatic invokestatic = marshalerMethod.getInvokeStatic(sootMethod.getDeclaringClass());
trampolines.add(invokestatic);
Value valueClass = ldcClass(fn, valueClassName, env);
Variable handle = fn.newVariable(I64);
fn.add(new Ptrtoint(handle, nativeValue, I64));
Value object = call(fn, invokestatic.getFunctionRef(), env, valueClass, handle.ref(), new IntegerConstant(flags));
if (marshaledArg != null) {
marshaledArg.handle = handle.ref();
marshaledArg.object = object;
}
return object;
}
Aggregations