Search in sources :

Example 1 with AnnotationTag

use of soot.tagkit.AnnotationTag in project robovm by robovm.

the class ObjCMemberPlugin method addTypeEncodingAnnotation.

static void addTypeEncodingAnnotation(SootMethod method, String encoding) {
    AnnotationTag annotationTag = new AnnotationTag(TYPE_ENCODING, 1);
    annotationTag.addElem(new AnnotationStringElem(encoding, 's', "value"));
    addRuntimeVisibleAnnotation(method, annotationTag);
}
Also used : AnnotationStringElem(soot.tagkit.AnnotationStringElem) AnnotationTag(soot.tagkit.AnnotationTag)

Example 2 with AnnotationTag

use of soot.tagkit.AnnotationTag in project robovm by robovm.

the class AttributesEncoder method encodeAttributes.

private Constant encodeAttributes(Host host) {
    List<Value> attributes = new ArrayList<Value>();
    for (Tag tag : host.getTags()) {
        if (tag instanceof SourceFileTag) {
            // Skip. We don't need this at this time.
            Value sourceFile = getString(((SourceFileTag) tag).getSourceFile());
            attributes.add(new PackedStructureConstant(new PackedStructureType(I8, I8_PTR), new IntegerConstant(SOURCE_FILE), sourceFile));
        } else if (tag instanceof EnclosingMethodTag) {
            EnclosingMethodTag emt = (EnclosingMethodTag) tag;
            Value eClass = getString(emt.getEnclosingClass());
            Value eMethod = getStringOrNull(emt.getEnclosingMethod());
            Value eDesc = getStringOrNull(emt.getEnclosingMethodSig());
            attributes.add(new PackedStructureConstant(new PackedStructureType(I8, I8_PTR, I8_PTR, I8_PTR), new IntegerConstant(ENCLOSING_METHOD), eClass, eMethod, eDesc));
        } else if (tag instanceof SignatureTag) {
            Value signature = getString(((SignatureTag) tag).getSignature());
            attributes.add(new PackedStructureConstant(new PackedStructureType(I8, I8_PTR), new IntegerConstant(SIGNATURE), signature));
        } else if (tag instanceof InnerClassTag) {
            InnerClassTag ict = (InnerClassTag) tag;
            Value innerClass = getStringOrNull(ict.getInnerClass());
            Value outerClass = getStringOrNull(ict.getOuterClass());
            Value innerName = getStringOrNull(ict.getShortName());
            Value innerClassAccess = new IntegerConstant(ict.getAccessFlags());
            attributes.add(new PackedStructureConstant(new PackedStructureType(I8, I8_PTR, I8_PTR, I8_PTR, I32), new IntegerConstant(INNER_CLASS), innerClass, outerClass, innerName, innerClassAccess));
        } else if (tag instanceof AnnotationDefaultTag) {
            StructureConstant value = encodeAnnotationElementValue(((AnnotationDefaultTag) tag).getDefaultVal());
            attributes.add(new PackedStructureConstant(new PackedStructureType(I8, value.getType()), new IntegerConstant(ANNOTATION_DEFAULT), value));
        } else if (tag instanceof VisibilityAnnotationTag) {
            VisibilityAnnotationTag vat = (VisibilityAnnotationTag) tag;
            if (vat.getVisibility() == AnnotationConstants.RUNTIME_VISIBLE) {
                Type[] types = new Type[vat.getAnnotations().size()];
                Value[] values = new Value[vat.getAnnotations().size()];
                int i = 0;
                for (AnnotationTag at : vat.getAnnotations()) {
                    values[i] = encodeAnnotationTagValue(at);
                    types[i] = values[i].getType();
                    i++;
                }
                attributes.add(new PackedStructureConstant(new PackedStructureType(I8, I32, new PackedStructureType(types)), new IntegerConstant(RUNTIME_VISIBLE_ANNOTATIONS), new IntegerConstant(vat.getAnnotations().size()), new PackedStructureConstant(new PackedStructureType(types), values)));
            }
        } else if (tag instanceof VisibilityParameterAnnotationTag) {
            VisibilityParameterAnnotationTag vpat = (VisibilityParameterAnnotationTag) tag;
            List<Type> typesList = new ArrayList<Type>();
            List<Value> valuesList = new ArrayList<Value>();
            boolean hasRuntimeVisible = false;
            for (VisibilityAnnotationTag vat : vpat.getVisibilityAnnotations()) {
                typesList.add(I32);
                if (vat.getVisibility() == AnnotationConstants.RUNTIME_VISIBLE && vat.getAnnotations() != null && !vat.getAnnotations().isEmpty()) {
                    hasRuntimeVisible = true;
                    valuesList.add(new IntegerConstant(vat.getAnnotations().size()));
                    for (AnnotationTag at : vat.getAnnotations()) {
                        valuesList.add(encodeAnnotationTagValue(at));
                        typesList.add(valuesList.get(valuesList.size() - 1).getType());
                    }
                } else {
                    valuesList.add(new IntegerConstant(0));
                }
            }
            if (hasRuntimeVisible) {
                Type[] types = typesList.toArray(new Type[typesList.size()]);
                Value[] values = valuesList.toArray(new Value[valuesList.size()]);
                attributes.add(new PackedStructureConstant(new PackedStructureType(I8, I32, new PackedStructureType(types)), new IntegerConstant(RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS), new IntegerConstant(vpat.getVisibilityAnnotations().size()), new PackedStructureConstant(new PackedStructureType(types), values)));
            }
        }
    }
    if (host instanceof SootMethod) {
        List<SootClass> exceptions = ((SootMethod) host).getExceptions();
        if (!exceptions.isEmpty()) {
            Value[] values = new Value[exceptions.size()];
            for (int i = 0; i < exceptions.size(); i++) {
                String exName = getInternalName(exceptions.get(i));
                values[i] = getString(exName);
                addDependency(exName);
            }
            attributes.add(new PackedStructureConstant(new PackedStructureType(I8, I32, new ArrayType(exceptions.size(), I8_PTR)), new IntegerConstant(EXCEPTIONS), new IntegerConstant(exceptions.size()), new ArrayConstant(new ArrayType(exceptions.size(), I8_PTR), values)));
        }
    }
    if (attributes.isEmpty()) {
        return null;
    }
    attributes.add(0, new IntegerConstant(attributes.size()));
    Type[] types = new Type[attributes.size()];
    for (int i = 0; i < types.length; i++) {
        types[i] = attributes.get(i).getType();
    }
    return new PackedStructureConstant(new PackedStructureType(types), attributes.toArray(new Value[0]));
}
Also used : ArrayList(java.util.ArrayList) SourceFileTag(soot.tagkit.SourceFileTag) ArrayType(org.robovm.compiler.llvm.ArrayType) InnerClassTag(soot.tagkit.InnerClassTag) VisibilityAnnotationTag(soot.tagkit.VisibilityAnnotationTag) AnnotationTag(soot.tagkit.AnnotationTag) VisibilityParameterAnnotationTag(soot.tagkit.VisibilityParameterAnnotationTag) VisibilityAnnotationTag(soot.tagkit.VisibilityAnnotationTag) ArrayConstant(org.robovm.compiler.llvm.ArrayConstant) VisibilityParameterAnnotationTag(soot.tagkit.VisibilityParameterAnnotationTag) AnnotationDefaultTag(soot.tagkit.AnnotationDefaultTag) SootClass(soot.SootClass) PackedStructureType(org.robovm.compiler.llvm.PackedStructureType) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant) PackedStructureConstant(org.robovm.compiler.llvm.PackedStructureConstant) EnclosingMethodTag(soot.tagkit.EnclosingMethodTag) PackedStructureType(org.robovm.compiler.llvm.PackedStructureType) ArrayType(org.robovm.compiler.llvm.ArrayType) Type(org.robovm.compiler.llvm.Type) StructureConstant(org.robovm.compiler.llvm.StructureConstant) PackedStructureConstant(org.robovm.compiler.llvm.PackedStructureConstant) Value(org.robovm.compiler.llvm.Value) SignatureTag(soot.tagkit.SignatureTag) SootMethod(soot.SootMethod) Tag(soot.tagkit.Tag) AnnotationDefaultTag(soot.tagkit.AnnotationDefaultTag) VisibilityAnnotationTag(soot.tagkit.VisibilityAnnotationTag) InnerClassTag(soot.tagkit.InnerClassTag) SignatureTag(soot.tagkit.SignatureTag) AnnotationTag(soot.tagkit.AnnotationTag) SourceFileTag(soot.tagkit.SourceFileTag) EnclosingMethodTag(soot.tagkit.EnclosingMethodTag) VisibilityParameterAnnotationTag(soot.tagkit.VisibilityParameterAnnotationTag)

Example 3 with AnnotationTag

use of soot.tagkit.AnnotationTag in project robovm by robovm.

the class BridgeMethodCompiler method doCompile.

protected Function doCompile(ModuleBuilder moduleBuilder, SootMethod method) {
    validateBridgeMethod(method);
    AnnotationTag bridgeAnnotation = getAnnotation(method, BRIDGE);
    boolean dynamic = readBooleanElem(bridgeAnnotation, "dynamic", false);
    boolean optional = readBooleanElem(bridgeAnnotation, "optional", false);
    boolean useCWrapper = requiresCWrapper(method);
    Function fn = createMethodFunction(method);
    moduleBuilder.addFunction(fn);
    Type[] parameterTypes = fn.getType().getParameterTypes();
    String[] parameterNames = fn.getParameterNames();
    ArrayList<Argument> args = new ArrayList<Argument>();
    for (int i = 0; i < parameterTypes.length; i++) {
        args.add(new Argument(new VariableRef(parameterNames[i], parameterTypes[i])));
    }
    VariableRef env = fn.getParameterRef(0);
    // Load the address of the resolved @Bridge method
    Variable targetFn = fn.newVariable(I8_PTR);
    if (!dynamic) {
        Global targetFnPtr = new Global(Symbols.bridgePtrSymbol(method), _private, new NullConstant(I8_PTR));
        moduleBuilder.addGlobal(targetFnPtr);
        fn.add(new Load(targetFn, targetFnPtr.ref()));
        Label nullLabel = new Label();
        Label notNullLabel = new Label();
        Variable nullCheck = fn.newVariable(I1);
        fn.add(new Icmp(nullCheck, Condition.eq, targetFn.ref(), new NullConstant(I8_PTR)));
        fn.add(new Br(nullCheck.ref(), fn.newBasicBlockRef(nullLabel), fn.newBasicBlockRef(notNullLabel)));
        fn.newBasicBlock(nullLabel);
        call(fn, optional ? BC_THROW_UNSATISIFED_LINK_ERROR_OPTIONAL_BRIDGE_NOT_BOUND : BC_THROW_UNSATISIFED_LINK_ERROR_BRIDGE_NOT_BOUND, env, moduleBuilder.getString(className), moduleBuilder.getString(method.getName()), moduleBuilder.getString(getDescriptor(method)));
        fn.add(new Unreachable());
        fn.newBasicBlock(notNullLabel);
    } else {
        // Dynamic @Bridge methods pass the target function pointer as a
        // long in the first parameter.
        fn.add(new Inttoptr(targetFn, fn.getParameterRef(1), targetFn.getType()));
        args.remove(1);
    }
    // Marshal args
    // Remove Env* from args
    args.remove(0);
    // Save the Object->handle mapping for each marshaled object. We need it
    // after the native call to call updateObject() on the marshaler for 
    // each value. Since the LLVM variables that store these values are used 
    // after the native call we get the nice side effect that neither the
    // Java objects nor the handles can be garbage collected while we're in
    // native code.
    List<MarshaledArg> marshaledArgs = new ArrayList<MarshaledArg>();
    FunctionType targetFnType = getBridgeFunctionType(method, dynamic, false);
    Type[] targetParameterTypes = targetFnType.getParameterTypes();
    if (!method.isStatic()) {
        MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(new MarshalSite(method, MarshalSite.RECEIVER));
        MarshaledArg marshaledArg = new MarshaledArg();
        marshaledArg.paramIndex = MarshalSite.RECEIVER;
        marshaledArgs.add(marshaledArg);
        Type nativeType = targetParameterTypes[0];
        Value nativeValue = marshalObjectToNative(fn, marshalerMethod, marshaledArg, useCWrapper ? I8_PTR : nativeType, env, args.get(0).getValue(), MarshalerFlags.CALL_TYPE_BRIDGE);
        args.set(0, new Argument(nativeValue));
    }
    for (int i = 0, argIdx = 0; i < method.getParameterCount(); i++) {
        if (dynamic && i == 0) {
            // Skip the target function pointer for dynamic bridge methods.
            continue;
        }
        if (!method.isStatic() && argIdx == 0) {
            // Skip the receiver in args. It doesn't correspond to a parameter.
            argIdx++;
        }
        soot.Type type = method.getParameterType(i);
        if (needsMarshaler(type)) {
            MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(new MarshalSite(method, i));
            // The return type of the marshaler's toNative() method is derived from the target function type.
            Type nativeType = targetParameterTypes[argIdx];
            if (nativeType instanceof PrimitiveType) {
                Value nativeValue = marshalValueObjectToNative(fn, marshalerMethod, nativeType, env, args.get(argIdx).getValue(), MarshalerFlags.CALL_TYPE_BRIDGE);
                args.set(argIdx, new Argument(nativeValue));
            } else {
                ParameterAttribute[] parameterAttributes = new ParameterAttribute[0];
                if (isPassByValue(method, i) || isStructRet(method, i)) {
                    // 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(fn, CHECK_NULL, env, args.get(argIdx).getValue());
                }
                MarshaledArg marshaledArg = new MarshaledArg();
                marshaledArg.paramIndex = i;
                marshaledArgs.add(marshaledArg);
                Value nativeValue = marshalObjectToNative(fn, marshalerMethod, marshaledArg, useCWrapper ? I8_PTR : nativeType, env, args.get(argIdx).getValue(), MarshalerFlags.CALL_TYPE_BRIDGE);
                args.set(argIdx, new Argument(nativeValue, parameterAttributes));
            }
        } else {
            args.set(argIdx, new Argument(marshalPrimitiveToNative(fn, method, i, args.get(argIdx).getValue())));
        }
        argIdx++;
    }
    Variable structResult = null;
    Value targetFnRef = null;
    if (useCWrapper) {
        args.add(0, new Argument(targetFn.ref()));
        if (targetFnType.getReturnType() instanceof StructureType) {
            // Allocate space on the stack big enough to hold the returned struct
            Variable tmp = fn.newVariable(new PointerType(targetFnType.getReturnType()));
            fn.add(new Alloca(tmp, targetFnType.getReturnType()));
            structResult = fn.newVariable(I8_PTR);
            fn.add(new Bitcast(structResult, tmp.ref(), I8_PTR));
            args.add(1, new Argument(structResult.ref()));
        }
        String wrapperName = Symbols.bridgeCSymbol(method);
        FunctionType wrapperFnType = getBridgeFunctionType(method, dynamic, true);
        getCWrapperFunctions().add(createBridgeCWrapper(targetFnType.getReturnType(), targetFnType.getParameterTypes(), wrapperFnType.getParameterTypes(), wrapperName));
        FunctionRef wrapperFnRef = getBridgeCWrapperRef(targetFnType, wrapperName);
        moduleBuilder.addFunctionDeclaration(new FunctionDeclaration(wrapperFnRef));
        targetFnRef = wrapperFnRef;
    } else {
        Variable tmp = fn.newVariable(targetFnType);
        fn.add(new Bitcast(tmp, targetFn.ref(), targetFnType));
        targetFnRef = tmp.ref();
    }
    // Execute the call to native code
    BasicBlockRef bbSuccess = fn.newBasicBlockRef(new Label("success"));
    BasicBlockRef bbFailure = fn.newBasicBlockRef(new Label("failure"));
    pushNativeFrame(fn);
    trycatchAllEnter(fn, env, bbSuccess, bbFailure);
    fn.newBasicBlock(bbSuccess.getLabel());
    Value result = callWithArguments(fn, targetFnRef, args);
    trycatchLeave(fn, env);
    popNativeFrame(fn);
    updateObject(method, fn, env, MarshalerFlags.CALL_TYPE_BRIDGE, marshaledArgs);
    // Marshal the return value
    if (needsMarshaler(method.getReturnType())) {
        MarshalerMethod marshalerMethod = config.getMarshalerLookup().findMarshalerMethod(new MarshalSite(method));
        String targetClassName = getInternalName(method.getReturnType());
        if (structResult != null) {
            // Copy to the heap.
            DataLayout dataLayout = config.getDataLayout();
            Value heapCopy = call(fn, BC_COPY_STRUCT, env, structResult.ref(), new IntegerConstant(dataLayout.getAllocSize(targetFnType.getReturnType())));
            result = marshalNativeToObject(fn, marshalerMethod, null, env, targetClassName, heapCopy, MarshalerFlags.CALL_TYPE_BRIDGE);
        } else if (targetFnType.getReturnType() instanceof PrimitiveType) {
            result = marshalNativeToValueObject(fn, marshalerMethod, env, targetClassName, result, MarshalerFlags.CALL_TYPE_BRIDGE);
        } else {
            result = marshalNativeToObject(fn, marshalerMethod, null, env, targetClassName, result, MarshalerFlags.CALL_TYPE_BRIDGE);
        }
    } else {
        result = marshalNativeToPrimitive(fn, method, result);
    }
    fn.add(new Ret(result));
    fn.newBasicBlock(bbFailure.getLabel());
    trycatchLeave(fn, env);
    popNativeFrame(fn);
    Value ex = call(fn, BC_EXCEPTION_CLEAR, env);
    // Call Marshaler.updateObject() for each object that was marshaled before
    // the call.
    updateObject(method, fn, env, MarshalerFlags.CALL_TYPE_BRIDGE, marshaledArgs);
    call(fn, BC_THROW, env, ex);
    fn.add(new Unreachable());
    return fn;
}
Also used : MarshalSite(org.robovm.compiler.MarshalerLookup.MarshalSite) ParameterAttribute(org.robovm.compiler.llvm.ParameterAttribute) Ret(org.robovm.compiler.llvm.Ret) VariableRef(org.robovm.compiler.llvm.VariableRef) Variable(org.robovm.compiler.llvm.Variable) Argument(org.robovm.compiler.llvm.Argument) ArrayList(java.util.ArrayList) Label(org.robovm.compiler.llvm.Label) Inttoptr(org.robovm.compiler.llvm.Inttoptr) PointerType(org.robovm.compiler.llvm.PointerType) Global(org.robovm.compiler.llvm.Global) AnnotationTag(soot.tagkit.AnnotationTag) Function(org.robovm.compiler.llvm.Function) FunctionDeclaration(org.robovm.compiler.llvm.FunctionDeclaration) BasicBlockRef(org.robovm.compiler.llvm.BasicBlockRef) Unreachable(org.robovm.compiler.llvm.Unreachable) PrimitiveType(org.robovm.compiler.llvm.PrimitiveType) FunctionRef(org.robovm.compiler.llvm.FunctionRef) DataLayout(org.robovm.compiler.llvm.DataLayout) Load(org.robovm.compiler.llvm.Load) Alloca(org.robovm.compiler.llvm.Alloca) FunctionType(org.robovm.compiler.llvm.FunctionType) NullConstant(org.robovm.compiler.llvm.NullConstant) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant) Br(org.robovm.compiler.llvm.Br) StructureType(org.robovm.compiler.llvm.StructureType) PointerType(org.robovm.compiler.llvm.PointerType) LongType(soot.LongType) Type(org.robovm.compiler.llvm.Type) PrimitiveType(org.robovm.compiler.llvm.PrimitiveType) FunctionType(org.robovm.compiler.llvm.FunctionType) Bitcast(org.robovm.compiler.llvm.Bitcast) StructureType(org.robovm.compiler.llvm.StructureType) Value(org.robovm.compiler.llvm.Value) MarshalerMethod(org.robovm.compiler.MarshalerLookup.MarshalerMethod) PointerMarshalerMethod(org.robovm.compiler.MarshalerLookup.PointerMarshalerMethod) Icmp(org.robovm.compiler.llvm.Icmp)

Example 4 with AnnotationTag

use of soot.tagkit.AnnotationTag in project robovm by robovm.

the class Bro method getArrayDimensions.

public static int[] getArrayDimensions(SootMethod method, int paramIndex) {
    AnnotationTag annotation = paramIndex == -1 ? getArrayAnnotation(method) : getArrayAnnotation(method, paramIndex);
    if (annotation == null) {
        return null;
    }
    ArrayList<AnnotationElem> values = ((AnnotationArrayElem) annotation.getElemAt(0)).getValues();
    int[] dims = new int[values.size()];
    for (int i = 0; i < dims.length; i++) {
        dims[i] = ((AnnotationIntElem) values.get(i)).getValue();
    }
    return dims;
}
Also used : AnnotationTag(soot.tagkit.AnnotationTag) AnnotationArrayElem(soot.tagkit.AnnotationArrayElem) AnnotationElem(soot.tagkit.AnnotationElem)

Example 5 with AnnotationTag

use of soot.tagkit.AnnotationTag in project robovm by robovm.

the class MarshalerLookup method findMarshalerMethod.

public MarshalerMethod findMarshalerMethod(MarshalSite marshalSite) {
    int pidx = marshalSite.paramIdx;
    if (pidx != MarshalSite.RECEIVER) {
        // Use @Marshaler annotation on method or parameter at paramIndex if there is one 
        AnnotationTag anno = pidx == MarshalSite.RETURN_TYPE ? getMarshalerAnnotation(marshalSite.method) : getMarshalerAnnotation(marshalSite.method, pidx);
        if (anno != null) {
            AnnotationClassElem elem = (AnnotationClassElem) getElemByName(anno, "value");
            String name = getInternalNameFromDescriptor(elem.getDesc());
            Clazz marshalerClazz = config.getClazzes().load(name);
            if (marshalerClazz != null) {
                Marshaler marshaler = new Marshaler(marshalerClazz);
                if (marshaler.canMarshal(marshalSite)) {
                    return marshaler.getMarshalerMethod(marshalSite);
                }
            }
            throw new IllegalArgumentException(String.format("@Marshaler %s specified for %s of %s method %s can " + "not be used to marshal %s", name.replace('/', '.'), (pidx == MarshalSite.RETURN_TYPE ? "return type" : "parameter " + (pidx + 1)), marshalSite.callTypeName, marshalSite.method, marshalSite.type));
        }
    }
    Marshaler marshaler = findMarshalers(marshalSite);
    if (marshaler != null) {
        return marshaler.getMarshalerMethod(marshalSite);
    }
    throw new IllegalArgumentException(String.format("No @Marshaler found for %s of %s method %s", (pidx == MarshalSite.RECEIVER ? "receiver" : (pidx == MarshalSite.RETURN_TYPE ? "return type" : "parameter " + (pidx + 1))), marshalSite.callTypeName, marshalSite.method));
}
Also used : AnnotationTag(soot.tagkit.AnnotationTag) AnnotationClassElem(soot.tagkit.AnnotationClassElem) Clazz(org.robovm.compiler.clazz.Clazz)

Aggregations

AnnotationTag (soot.tagkit.AnnotationTag)37 VisibilityAnnotationTag (soot.tagkit.VisibilityAnnotationTag)22 VisibilityParameterAnnotationTag (soot.tagkit.VisibilityParameterAnnotationTag)20 ArrayList (java.util.ArrayList)15 AnnotationAnnotationElem (soot.tagkit.AnnotationAnnotationElem)11 AnnotationElem (soot.tagkit.AnnotationElem)11 Tag (soot.tagkit.Tag)10 AnnotationClassElem (soot.tagkit.AnnotationClassElem)7 AnnotationDefaultTag (soot.tagkit.AnnotationDefaultTag)7 AnnotationStringElem (soot.tagkit.AnnotationStringElem)7 EnclosingMethodTag (soot.tagkit.EnclosingMethodTag)7 InnerClassTag (soot.tagkit.InnerClassTag)7 SignatureTag (soot.tagkit.SignatureTag)7 AnnotationArrayElem (soot.tagkit.AnnotationArrayElem)6 SootMethod (soot.SootMethod)4 HashSet (java.util.HashSet)3 List (java.util.List)3 AnnotationElement (org.jf.dexlib2.iface.AnnotationElement)3 EncodedValue (org.jf.dexlib2.iface.value.EncodedValue)3 ImmutableAnnotation (org.jf.dexlib2.immutable.ImmutableAnnotation)3