Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   * Copyright (C) 2012 Trillian Mobile AB
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License
   * as published by the Free Software Foundation; either version 2
   * of the License, or (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program.  If not, see <http://www.gnu.org/licenses/gpl-2.0.html>.
  */
 package org.robovm.compiler;
 
 import static org.robovm.compiler.Annotations.*;
 import static org.robovm.compiler.Bro.*;
 import static org.robovm.compiler.Functions.*;
 import static org.robovm.compiler.Types.*;
 import static org.robovm.compiler.llvm.Type.*;
 
 import java.util.List;
 
 
 import soot.FloatType;
 import soot.LongType;
 import soot.PrimType;
 import soot.RefType;
 import soot.SootClass;
 import soot.VoidType;


 
 public abstract class BroMethodCompiler extends AbstractMethodCompiler {
 
     public BroMethodCompiler(Config config) {
         super(config);
     }
 
     protected Value ldcClass(Function fnString nameValue env) {
         if (isArray(name) && isPrimitiveBaseType(name)) {
             String primitiveDesc = name.substring(name.length() - 1);
             Variable result = fn.newVariable();
             fn.add(new Load(resultnew ConstantBitcast(
                     new GlobalRef("array_" + primitiveDesc), new PointerType())));
             return result.ref();
         } else {
             FunctionRef ldcClassFn = null;
             if (name.equals(this.)) {
                 ldcClassFn = FunctionBuilder.ldcInternal(this.).ref();
             } else {
                 Trampoline trampoline = new LdcClass(this.name);
                 .add(trampoline);
                 ldcClassFn = trampoline.getFunctionRef();
             }
             return call(fnldcClassFnenv);
         }
     }
    protected Value marshalNativeToPrimitive(Function fnSootMethod methodint paramIndexValue value) {
        soot.Type type = method.getParameterType(paramIndex);
        if (hasPointerAnnotation(methodparamIndex)) {
            value = marshalPointerToLong(fnvalue);
        } else if (hasMachineSizedFloatAnnotation(methodparamIndex) && type.equals(DoubleType.v())) {
            value = marshalMachineSizedFloatToDouble(fnvalue);
        } else if (hasMachineSizedFloatAnnotation(methodparamIndex) && type.equals(FloatType.v())) {
            value = marshalMachineSizedFloatToFloat(fnvalue);
        } else if (hasMachineSizedSIntAnnotation(methodparamIndex) && type.equals(LongType.v())) {
            value = marshalMachineSizedSIntToLong(fnvalue);
        } else if (hasMachineSizedUIntAnnotation(methodparamIndex) && type.equals(LongType.v())) {
            value = marshalMachineSizedUIntToLong(fnvalue);
        }
        return value;
    }
    protected Value marshalPrimitiveToNative(Function fnSootMethod methodint paramIndexValue value) {
        soot.Type type = method.getParameterType(paramIndex);
        if (hasPointerAnnotation(methodparamIndex)) {
            value = marshalLongToPointer(fnvalue);
        } else if (hasMachineSizedFloatAnnotation(methodparamIndex) && type.equals(DoubleType.v())) {
            value = marshalDoubleToMachineSizedFloat(fnvalue);
        } else if (hasMachineSizedFloatAnnotation(methodparamIndex) && type.equals(FloatType.v())) {
            value = marshalFloatToMachineSizedFloat(fnvalue);
        } else if (hasMachineSizedSIntAnnotation(methodparamIndex) && type.equals(LongType.v())) {
            value = marshalLongToMachineSizedInt(fnvalue);
        } else if (hasMachineSizedUIntAnnotation(methodparamIndex) && type.equals(LongType.v())) {
            value = marshalLongToMachineSizedInt(fnvalue);
        }
        return value;
    }
    
    protected Value marshalNativeToPrimitive(Function fnSootMethod methodValue value) {
        soot.Type type = method.getReturnType();
        if (hasPointerAnnotation(method)) {
            value = marshalPointerToLong(fnvalue);
        } else if (hasMachineSizedFloatAnnotation(method) && type.equals(DoubleType.v())) {
            value = marshalMachineSizedFloatToDouble(fnvalue);
        } else if (hasMachineSizedFloatAnnotation(method) && type.equals(FloatType.v())) {
            value = marshalMachineSizedFloatToFloat(fnvalue);
        } else if (hasMachineSizedSIntAnnotation(method) && type.equals(LongType.v())) {
            value = marshalMachineSizedSIntToLong(fnvalue);
        } else if (hasMachineSizedUIntAnnotation(method) && type.equals(LongType.v())) {
            value = marshalMachineSizedUIntToLong(fnvalue);
        }
        return value;
    }
    protected Value marshalPrimitiveToNative(Function fnSootMethod methodValue value) {
        soot.Type type = method.getReturnType();
        if (hasPointerAnnotation(method)) {
            value = marshalLongToPointer(fnvalue);
        } else if (hasMachineSizedFloatAnnotation(method) && type.equals(DoubleType.v())) {
            value = marshalDoubleToMachineSizedFloat(fnvalue);
        } else if (hasMachineSizedFloatAnnotation(method) && type.equals(FloatType.v())) {
            value = marshalFloatToMachineSizedFloat(fnvalue);
        } else if (hasMachineSizedSIntAnnotation(method) && type.equals(LongType.v())) {
            value = marshalLongToMachineSizedInt(fnvalue);
        } else if (hasMachineSizedUIntAnnotation(method) && type.equals(LongType.v())) {
            value = marshalLongToMachineSizedInt(fnvalue);
        }
        return value;
    }
    
    public static class MarshaledArg {
        public Value object;
        public Value handle;
        public int paramIndex;
    }
    
    protected Value marshalNativeToObject(Function fnMarshalerMethod marshalerMethod
            MarshaledArg marshaledArgValue env,  String valueClassName
            Value nativeValuelong flags) {
        
        if (nativeValue.getType() instanceof StructureType) {
            nativeValue = createStackCopy(fnnativeValue);
        }
        
        Invokestatic invokestatic = marshalerMethod.getInvokeStatic(
                .getDeclaringClass());
        .add(invokestatic);
    
        Value valueClass = ldcClass(fnvalueClassNameenv);
        
        Variable handle = fn.newVariable();
        fn.add(new Ptrtoint(handlenativeValue));
        
        Value object = call(fninvokestatic.getFunctionRef(), 
                envvalueClasshandle.ref(), new IntegerConstant(flags));
        
        if (marshaledArg != null) {
            marshaledArg.handle = handle.ref();
            marshaledArg.object = object;
        }
        
        return object;
    }
    protected Value createStackCopy(Function fnValue value) {
        Variable stackCopy = fn.newVariable(new PointerType(value.getType()));
        fn.add(new Alloca(stackCopyvalue.getType()));
        fn.add(new Store(valuestackCopy.ref()));
        return stackCopy.ref();
    }
    
    protected Value marshalNativeToValueObject(Function fnMarshalerMethod marshalerMethodValue env
            String valueClassNameValue nativeValuelong flags) {
        
        Invokestatic invokeToObject = marshalerMethod.getInvokeStatic(
                .getDeclaringClass());
        .add(invokeToObject);
    
        Value valueClass = ldcClass(fnvalueClassNameenv);
        
        nativeValue = marshalNativeToPrimitive(fnmarshalerMethod.getMethod(), 1, nativeValue);
        
        return call(fninvokeToObject.getFunctionRef(), envvalueClassnativeValuenew IntegerConstant(flags));
    }
    private List<ValuearrayDimensionsValues(int[] dimensions) {
        List<Valuel = new ArrayList<>();
        for (int i = 0; i < dimensions.lengthi++) {
            l.add(new IntegerConstant(dimensions[i]));
        }
        return l;
    }
    protected Value marshalNativeToArray(Function fnMarshalerMethod marshalerMethodValue env
            String arrayClassNameValue nativeValuelong flagsint[] dimensions) {
                
        Invokestatic invokeToObject = marshalerMethod.getInvokeStatic(.getDeclaringClass());
        .add(invokeToObject);
        Variable handle = fn.newVariable();
        fn.add(new Ptrtoint(handlenativeValue)); 
        Value valueClass = ldcClass(fnarrayClassNameenv);
        List<Valueargs = new ArrayList<>();
        args.add(env);
        args.add(valueClass);
        args.add(handle.ref());
        args.add(new IntegerConstant(flags));
        args.addAll(arrayDimensionsValues(dimensions));
        
        return call(fninvokeToObject.getFunctionRef(), args);
    }
    
    protected Value marshalPointerToLong(Function fnValue pointer) {
        Variable result = fn.newVariable();
        fn.add(new Ptrtoint(resultpointer));
        return result.ref();
    }
    protected Value marshalMachineSizedSIntToLong(Function fnValue value) {
        if (.getArch().is32Bit()) {
            Variable result = fn.newVariable();
            fn.add(new Sext(resultvalue));
            return result.ref();
        } else {
            return value;
        }
    }
    protected Value marshalMachineSizedUIntToLong(Function fnValue value) {
        if (.getArch().is32Bit()) {
            Variable result = fn.newVariable();
            fn.add(new Zext(resultvalue));
            return result.ref();
        } else {
            return value;
        }
    }
    protected Value marshalMachineSizedFloatToDouble(Function fnValue value) {
        if (.getArch().is32Bit()) {
            Variable result = fn.newVariable();
            fn.add(new Fpext(resultvalue));
            return result.ref();
        } else {
            return value;
        }
    }
    protected Value marshalMachineSizedFloatToFloat(Function fnValue value) {
        if (!.getArch().is32Bit()) {
            Variable result = fn.newVariable();
            fn.add(new Fptrunc(resultvalue));
            return result.ref();
        } else {
            return value;
        }
    }
    protected Value marshalObjectToNative(Function fnMarshalerMethod marshalerMethodMarshaledArg marshaledArg
            Type nativeTypeValue envValue objectlong flags) {
        return marshalObjectToNative(fnmarshalerMethodmarshaledArgnativeTypeenvobjectflagsfalse);
    }
    
    protected Value marshalObjectToNative(Function fnMarshalerMethod marshalerMethodMarshaledArg marshaledArg
            Type nativeTypeValue envValue objectlong flagsboolean smallStructRet) {
        
        Invokestatic invokestatic = marshalerMethod.getInvokeStatic(.getDeclaringClass());
        .add(invokestatic);
        Value handle = call(fninvokestatic.getFunctionRef(), 
                envobjectnew IntegerConstant(flags));
    
        Variable nativeValue = fn.newVariable(nativeType);
        if (nativeType instanceof StructureType || nativeType instanceof ArrayType || smallStructRet) {
            Variable tmp = fn.newVariable(new PointerType(nativeType));
            fn.add(new Inttoptr(tmphandletmp.getType()));
            fn.add(new Load(nativeValuetmp.ref()));
        } else {
            fn.add(new Inttoptr(nativeValuehandlenativeType));
        }
        
        if (marshaledArg != null) {
            marshaledArg.handle = handle;
            marshaledArg.object = object;
        }
        
        return nativeValue.ref();
    }
    
    protected Value marshalValueObjectToNative(Function fnMarshalerMethod marshalerMethod
            Type nativeTypeValue envValue objectlong flags) {
        
        Invokestatic invokestatic = marshalerMethod.getInvokeStatic(
                .getDeclaringClass());
        .add(invokestatic);
        Value result = call(fninvokestatic.getFunctionRef(), envobjectnew IntegerConstant(flags));
        return marshalPrimitiveToNative(fnmarshalerMethod.getMethod(), result);
    }
    
    protected void marshalArrayToNative(Function fnMarshalerMethod marshalerMethod
            Value envValue objectValue destPtrlong flagsint[] dimensions) {
        
        Invokestatic invokestatic = marshalerMethod.getInvokeStatic(.getDeclaringClass());
        .add(invokestatic);
        Variable handle = fn.newVariable();
        fn.add(new Ptrtoint(handledestPtr)); 
        List<Valueargs = new ArrayList<>();
        args.add(env);
        args.add(object);
        args.add(handle.ref());
        args.add(new IntegerConstant(flags));
        args.addAll(arrayDimensionsValues(dimensions));
        call(fninvokestatic.getFunctionRef(), args);
    }
    
    protected Value marshalLongToPointer(Function fnValue handle) {
        Variable result = fn.newVariable();
        fn.add(new Inttoptr(resulthandle));
        return result.ref();
    }
    protected Value marshalLongToMachineSizedInt(Function fnValue value) {
        if (.getArch().is32Bit()) {
            Variable result = fn.newVariable();
            fn.add(new Trunc(resultvalue));
            return result.ref();
        } else {
            return value;
        }
    }
    protected Value marshalDoubleToMachineSizedFloat(Function fnValue value) {
        if (.getArch().is32Bit()) {
            Variable result = fn.newVariable();
            fn.add(new Fptrunc(resultvalue));
            return result.ref();
        } else {
            return value;
        }
    }
    protected Value marshalFloatToMachineSizedFloat(Function fnValue value) {
        if (!.getArch().is32Bit()) {
            Variable result = fn.newVariable();
            fn.add(new Fpext(resultvalue));
            return result.ref();
        } else {
            return value;
        }
    }
    private Type getReturnType(String annoSootMethod method) {
        soot.Type sootType = method.getReturnType();
        if (hasPointerAnnotation(method)) {
            if (!sootType.equals(LongType.v())) {
                throw new IllegalArgumentException(anno + " annotated method " 
                        + method + " must return long when annotated with @Pointer");
            }
            return ;
        }        
        if (hasMachineSizedFloatAnnotation(method)) {
            if (!sootType.equals(DoubleType.v()) && !sootType.equals(FloatType.v())) {
                throw new IllegalArgumentException(anno + " annotated method " 
                        + method + " must return float or double when annotated with @MachineSizedFloat");
            }
            return .getArch().is32Bit() ?  : ;
        }        
        if (hasMachineSizedSIntAnnotation(method) || hasMachineSizedUIntAnnotation(method)) {
            if (!sootType.equals(LongType.v())) {
                throw new IllegalArgumentException(anno + " annotated method " 
                        + method + " must return long when annotated with @MachineSizedSInt or @MachineSizedUInt");
            }
            return .getArch().is32Bit() ?  : ;
        }        
        if (isStruct(sootType)) {
            if (!isPassByValue(method)) {
                // Structs are returned by reference by default
                return new PointerType(getStructType(sootType));
            }
            // Only small Structs can be returned by value. How small is defined by the target ABI.
            // Larger Structs should be passed as parameters with the @StructRet annotation.
            return getStructType(sootType);
        } else if (isNativeObject(sootType)) {
            // NativeObjects are always returned by reference.
            return ;
        } else if (sootType instanceof PrimType || sootType == VoidType.v()) {
            return getType(sootType);
        }
        MarshalerMethod marshalerMethod = .getMarshalerLookup().findMarshalerMethod(new MarshalSite(method));
        if (marshalerMethod instanceof ValueMarshalerMethod) {
            return ((ValueMarshalerMethodmarshalerMethod).getNativeType(.getArch());
        } else {
            return ;
        }
    }
    
    private Type getParameterType(String annoSootMethod methodint i) {
        soot.Type sootType = method.getParameterType(i);
        if (hasPointerAnnotation(methodi)) {
            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 ;
        }
        if (hasMachineSizedFloatAnnotation(methodi)) {
            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 .getArch().is32Bit() ?  : ;
        }
        if (hasMachineSizedSIntAnnotation(methodi) || hasMachineSizedUIntAnnotation(methodi)) {
            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 .getArch().is32Bit() ?  : ;
        }        
        if (hasStructRetAnnotation(methodi)) {
            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)) {
            // Structs are always passed as pointers. The LLVM 
            // byval attribute  will be added to the parameter when making the 
            // call if @ByVal has been specified to get the desired pass by 
            // value semantics.
            return new PointerType(getStructType(sootType));
        } else if (isNativeObject(sootType)) {
            // NativeObjects are always passed by reference.
            return ;
        } else if (sootType instanceof PrimType) {
            return getType(sootType);
        }
        
        MarshalerMethod marshalerMethod = .getMarshalerLookup().findMarshalerMethod(new MarshalSite(methodi));
        if (marshalerMethod instanceof ValueMarshalerMethod) {
            return ((ValueMarshalerMethodmarshalerMethod).getNativeType(.getArch());
        } else {
            return ;
        }
    }
    public FunctionType getBridgeFunctionType(SootMethod methodboolean dynamic) {
        return getBridgeOrCallbackFunctionType("@Bridge"methoddynamic);
    }
    
        return getBridgeOrCallbackFunctionType("@Callback"methodfalse);
    }
    
    private FunctionType getBridgeOrCallbackFunctionType(String annoSootMethod methodboolean dynamic) {
        Type returnType = getReturnType(annomethod);
        
        List<TypeparamTypes = new ArrayList<>();
        for (int i = dynamic ? 1 : 0; i < method.getParameterCount(); i++) {
            paramTypes.add(getParameterType(annomethodi));
        }
        if (!method.isStatic()) {
            int idx = hasStructRetAnnotation(method, 0) ? 1 : 0;
            soot.Type sootType = method.getDeclaringClass().getType();
            if (isStruct(sootType)) {
                paramTypes.add(idxnew PointerType(getStructType(sootType)));
            } else if (isNativeObject(sootType)) {
                // NativeObjects are always passed by reference.
                paramTypes.add(idx);
            } else {
                throw new IllegalArgumentException("Receiver of non static " 
                        + anno + " method " + method 
                        + " must either be a Struct or a NativeObject");
            }
        }
        return new FunctionType(returnTypeparamTypes.toArray(new Type[paramTypes.size()]));
    }
    
    public StructureType getStructType(soot.Type t) {
        return getStructType(((RefTypet).getSootClass());                
    }
    
    public StructureType getStructType(SootClass clazz) {
        return getStructType(clazztrue);
    }
    
    private StructureType getStructType(SootClass clazzboolean 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(superclassfalse);
            }
        }
        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 && ((RefTyperetType).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(.getDataLayout(), typeresult[index]);
                }
            }
        }
        
        for (int i = 1; i < result.lengthi++) {
            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);
    }
    
    static Type mergeStructMemberTypes(DataLayout dataLayoutType t1Type t2) {
        int align1 = dataLayout.getAlignment(t1);
        int align2 = dataLayout.getAlignment(t2);
        int size1 = dataLayout.getStoreSize(t1);
        int size2 = dataLayout.getStoreSize(t2);
        
        Type result = align1 < align2 ? t2 : t1;
        int size = align1 < align2 ? size2 : size1;
        int pad = Math.max(size1size2) - size;
        if (pad > 0) {
            return new StructureType(resultnew ArrayType(pad));
        } else {
            return result;
        }
    }
    
    public Type getStructMemberType(SootMethod method) {
        String methodType = hasStructMemberAnnotation(method) ? "@StructMember" : "@GlobalValue";
        SootMethod getter = method.getParameterCount() == 0 ? method : null;
        SootMethod setter = getter == null ? methodnull;
        soot.Type type = getter != null 
                ? getter.getReturnType() : setter.getParameterType(0);
        Type memberType = null;
        if (getter != null && hasPointerAnnotation(getter) || setter != null && hasPointerAnnotation(setter, 0)) {
            memberType = ;
        } else if (getter != null && hasMachineSizedFloatAnnotation(getter) || setter != null && hasMachineSizedFloatAnnotation(setter, 0)) {
            memberType = .getArch().is32Bit() ?  : ;
        } else if (getter != null && (hasMachineSizedSIntAnnotation(getter) || hasMachineSizedUIntAnnotation(getter)) 
                || setter != null && (hasMachineSizedSIntAnnotation(setter, 0) || hasMachineSizedUIntAnnotation(setter, 0))) {
            memberType = .getArch().is32Bit() ?  : ;
        } 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.ArrayTypetype). != 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.ArrayTypetype;
                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 = .getMarshalerLookup()
                        .findMarshalerMethod(getter != null ? new MarshalSite(getter) : new MarshalSite(setter, 0));
                baseType = getType(((ArrayMarshalerMethodmarshalerMethod).getBaseType());
            }
            
            if (baseType == null) {
                throw new IllegalArgumentException("Arrays of " + type + " is not supported");
            }
            long total = dimensions[0];
            for (int i = 1; i < dimensions.lengthi++) {
                total *= dimensions[i];
            }
            memberType = new ArrayType(totalbaseType);
        } 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 = ;
            } else {
                try {
                    memberType = getStructType(type);
                } catch (StackOverflowError e) {
                    throw new IllegalArgumentException("Struct type " + type + " refers to itself");
                }
            }
        } else if (isNativeObject(type)) {
            memberType = ;
        } else {
            MarshalerMethod marshalerMethod = .getMarshalerLookup()
                    .findMarshalerMethod(getter != null ? new MarshalSite(getter) : new MarshalSite(setter, 0));
            if (marshalerMethod instanceof ValueMarshalerMethod) {
                memberType = ((ValueMarshalerMethodmarshalerMethod).getNativeType(.getArch());
            } else {
                memberType = ;
            }
        }
        
        return memberType;
    }
    
    protected SootMethod createFakeStructRetMethod(SootMethod originalMethod) {
        // Create a new method with the same parameters but a @StructRet parameter inserted first
        @SuppressWarnings("unchecked")
        ArrayList<soot.TypenewParameterTypes = new ArrayList<soot.Type>(originalMethod.getParameterTypes());
        newParameterTypes.add(0, originalMethod.getReturnType());
        SootMethod method = new SootMethod(originalMethod.getName(), newParameterTypes, VoidType.v(), originalMethod.getModifiers());
        method.setDeclaringClass(originalMethod.getDeclaringClass());
        method.setDeclared(true);
        // Copy all annotations from the original method
        copyAnnotations(originalMethodmethod.);
        // Copy all parameter annotations from the original method to the copy shifting by 1
        copyParameterAnnotations(originalMethodmethod, 0, originalMethod.getParameterCount(), 1, .);
        // Add @StructRet to parameter 0
        return method;
    }
    protected Value loadValueForGetter(SootMethod methodFunction fnType memberType,
            Value memberPtrValue envlong 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 {
            Variable tmp = fn.newVariable(memberType);
            fn.add(new Load(tmpmemberPtr));
            result = tmp.ref();
        }
        
        if (needsMarshaler(type)) {
            MarshalerMethod marshalerMethod = .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(fnmarshalerMethodenv
                        targetClassNameresultflags);
            } else {
                if (memberType instanceof ArrayType) {
                    // Array
                    result = marshalNativeToArray(fnmarshalerMethodenv
                            targetClassNameresultflags,
                            getArrayDimensions(method));
                } else {
                    result = marshalNativeToObject(fnmarshalerMethodnullenv
                            targetClassNameresultflags);
                }
            }
        } else {
            result = marshalNativeToPrimitive(fnmethodresult);
        }
        return result;
    }
    protected void storeValueForSetter(SootMethod methodFunction function,
            Type memberTypeValue memberPtrValue envValue valuelong flags) {
        
        soot.Type type = method.getParameterType(0);
        if (needsMarshaler(type)) {
            MarshalerMethod marshalerMethod = .getMarshalerLookup().findMarshalerMethod(new MarshalSite(method, 0));
            
            if (memberType instanceof PrimitiveType) {
                value = marshalValueObjectToNative(functionmarshalerMethodmemberTypeenv
                        valueflags);
            } 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(functionenvvalue);
                }
                
                if (memberType instanceof ArrayType) {
                    // Array
                    marshalArrayToNative(functionmarshalerMethodenvvaluememberPtr
                            flagsgetArrayDimensions(method, 0));
                    value = null;
                } else {
                    value = marshalObjectToNative(functionmarshalerMethodnullmemberTypeenvvalue,
                            flags);
                }
            }
        } else {
            value = marshalPrimitiveToNative(functionmethod, 0, value);
        }
        if (value != null) {
            function.add(new Store(valuememberPtr));
        }
    }