use of soot.RefType in project robovm by robovm.
the class BroMethodCompiler method getStructMemberType.
public Type getStructMemberType(SootMethod method) {
String methodType = hasStructMemberAnnotation(method) ? "@StructMember" : "@GlobalValue";
SootMethod getter = method.getParameterCount() == 0 ? method : null;
SootMethod setter = getter == null ? method : null;
soot.Type type = getter != null ? getter.getReturnType() : setter.getParameterType(0);
Type memberType = null;
if (getter != null && hasPointerAnnotation(getter) || setter != null && hasPointerAnnotation(setter, 0)) {
memberType = I8_PTR;
} else if (getter != null && hasMachineSizedFloatAnnotation(getter) || setter != null && hasMachineSizedFloatAnnotation(setter, 0)) {
memberType = config.getArch().is32Bit() ? FLOAT : DOUBLE;
} else if (getter != null && (hasMachineSizedSIntAnnotation(getter) || hasMachineSizedUIntAnnotation(getter)) || setter != null && (hasMachineSizedSIntAnnotation(setter, 0) || hasMachineSizedUIntAnnotation(setter, 0))) {
memberType = config.getArch().is32Bit() ? I32 : I64;
} else if (type instanceof PrimType) {
memberType = getType(type);
} else if (getter != null && hasArrayAnnotation(getter) || setter != null && hasArrayAnnotation(setter, 0)) {
int[] dimensions = getter != null ? getArrayDimensions(getter) : getArrayDimensions(setter, 0);
if (dimensions == null || dimensions.length == 0) {
throw new IllegalArgumentException("No dimensions specified for @Array annotation on " + methodType + " " + (getter != null ? "getter" : "setter") + " " + method);
}
if (type instanceof soot.ArrayType && ((soot.ArrayType) type).numDimensions != dimensions.length) {
throw new IllegalArgumentException("Mismatch in number of dimennsions for @Array annotation " + "and type on " + methodType + " " + (getter != null ? "getter" : "setter") + " " + method);
}
Type baseType = null;
if (type instanceof soot.ArrayType) {
soot.ArrayType arrayType = (soot.ArrayType) type;
if (isStruct(arrayType.baseType)) {
// ByVal is implied for arrays of structs
try {
baseType = getStructType(arrayType.baseType);
} catch (StackOverflowError e) {
throw new IllegalArgumentException("Struct type " + type + " refers to itself");
}
} else {
baseType = getType(arrayType.baseType);
}
} else if (isStruct(type)) {
// ByVal is implied
try {
baseType = getStructType(type);
} catch (StackOverflowError e) {
throw new IllegalArgumentException("Struct type " + type + " refers to itself");
}
} else if (type instanceof RefType) {
MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(getter != null ? new MarshalSite(getter) : new MarshalSite(setter, 0));
baseType = getType(((ArrayMarshalerMethod) marshalerMethod).getBaseType());
}
if (baseType == null) {
throw new IllegalArgumentException("Arrays of " + type + " is not supported");
}
long total = dimensions[0];
for (int i = 1; i < dimensions.length; i++) {
total *= dimensions[i];
}
memberType = new ArrayType(total, baseType);
} else if (isStruct(type)) {
boolean byVal = getter != null ? isPassByValue(getter) : isPassByValue(setter, 0);
if (!byVal) {
// NOTE: We use i8* instead of <StructType>* to support pointers to recursive structs
memberType = I8_PTR;
} else {
try {
memberType = getStructType(type);
} catch (StackOverflowError e) {
throw new IllegalArgumentException("Struct type " + type + " refers to itself");
}
}
} else if (isNativeObject(type)) {
memberType = I8_PTR;
} else {
MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(getter != null ? new MarshalSite(getter) : new MarshalSite(setter, 0));
if (marshalerMethod instanceof ValueMarshalerMethod) {
memberType = ((ValueMarshalerMethod) marshalerMethod).getNativeType(config.getArch());
} else {
memberType = I8_PTR;
}
}
return memberType;
}
use of soot.RefType 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);
}
Aggregations