Search in sources :

Example 11 with NullConstant

use of org.robovm.compiler.llvm.NullConstant in project robovm by robovm.

the class NativeMethodCompiler method createNative.

private FunctionRef createNative(ModuleBuilder mb, SootMethod method) {
    String targetInternalName = getInternalName(method.getDeclaringClass());
    String methodName = method.getName();
    String methodDesc = getDescriptor(method);
    FunctionType nativeFunctionType = Types.getNativeFunctionType(methodDesc, method.isStatic());
    String shortName = mangleNativeMethod(targetInternalName, methodName);
    String longName = mangleNativeMethod(targetInternalName, methodName, methodDesc);
    /*
         * To support statically linked native method implementation we create
         * weak stub functions with the same names as the expected JNI functions
         * (long and short names). These will be discarded by the linker if
         * proper functions are available at link time.
         * 
         * The weak stub with the short JNI name just calls the weak stub with
         * the long name.
         * 
         * The weak stub with the long name calls _bcResolveNative() which will
         * try to resolve the native method against dynamically loaded JNI libs.
         * If _bcResolveNative() finds a matching symbol in a dynamic lib or an
         * implementation has previously been registered using JNI
         * RegisterNatives() that will be stored in the native method pointer
         * passed to it and returned. The stub will call the implementation
         * returned by _bcResolveNative(). If no implementation can be found
         * _bcResolveNative() throws an UnsatisfiedLinkError and doesn't return
         * to the stub.
         * 
         * The limitation of this approach is that RegisterNatives() only works
         * for dynamically linked native methods and can only be used prior to
         * the first call of such a method. Native methods can never be rewired
         * or unregistered.
         */
    /*
         * The function with the long JNI name. This is the one that calls
         * _bcResolveNative() and then calls the implementation.
         */
    Function fn = new FunctionBuilder(longName, nativeFunctionType).linkage(weak).build();
    Global g = new Global(Symbols.nativeMethodPtrSymbol(targetInternalName, methodName, methodDesc), new NullConstant(I8_PTR));
    mb.addGlobal(g);
    FunctionRef ldcFn = FunctionBuilder.ldcInternal(targetInternalName).ref();
    Value theClass = call(fn, ldcFn, fn.getParameterRef(0));
    Value implI8Ptr = call(fn, BC_RESOLVE_NATIVE, fn.getParameterRef(0), theClass, mb.getString(methodName), mb.getString(methodDesc), mb.getString(shortName), mb.getString(longName), g.ref());
    Variable nullTest = fn.newVariable(I1);
    fn.add(new Icmp(nullTest, Condition.ne, implI8Ptr, new NullConstant(I8_PTR)));
    Label trueLabel = new Label();
    Label falseLabel = new Label();
    fn.add(new Br(nullTest.ref(), fn.newBasicBlockRef(trueLabel), fn.newBasicBlockRef(falseLabel)));
    fn.newBasicBlock(falseLabel);
    if (fn.getType().getReturnType() instanceof IntegerType) {
        fn.add(new Ret(new IntegerConstant(0, (IntegerType) fn.getType().getReturnType())));
    } else if (fn.getType().getReturnType() instanceof FloatingPointType) {
        fn.add(new Ret(new FloatingPointConstant(0.0, (FloatingPointType) fn.getType().getReturnType())));
    } else if (fn.getType().getReturnType() instanceof PointerType) {
        fn.add(new Ret(new NullConstant((PointerType) fn.getType().getReturnType())));
    } else {
        fn.add(new Ret());
    }
    fn.newBasicBlock(trueLabel);
    Variable impl = fn.newVariable(nativeFunctionType);
    fn.add(new Bitcast(impl, implI8Ptr, impl.getType()));
    Value result = call(fn, impl.ref(), fn.getParameterRefs());
    fn.add(new Ret(result));
    mb.addFunction(fn);
    FunctionRef targetFn = fn.ref();
    if (!isLongNativeFunctionNameRequired(method)) {
        /*
             * Generate a function with the short JNI name. This just calls the
             * function with the long name.
             */
        Function fnShort = new FunctionBuilder(shortName, nativeFunctionType).linkage(weak).build();
        Value resultInner = call(fnShort, fn.ref(), fnShort.getParameterRefs());
        fnShort.add(new Ret(resultInner));
        mb.addFunction(fnShort);
        targetFn = fnShort.ref();
    }
    return targetFn;
}
Also used : Ret(org.robovm.compiler.llvm.Ret) Variable(org.robovm.compiler.llvm.Variable) FloatingPointConstant(org.robovm.compiler.llvm.FloatingPointConstant) FunctionType(org.robovm.compiler.llvm.FunctionType) Label(org.robovm.compiler.llvm.Label) NullConstant(org.robovm.compiler.llvm.NullConstant) PointerType(org.robovm.compiler.llvm.PointerType) FloatingPointType(org.robovm.compiler.llvm.FloatingPointType) Global(org.robovm.compiler.llvm.Global) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant) Br(org.robovm.compiler.llvm.Br) IntegerType(org.robovm.compiler.llvm.IntegerType) Function(org.robovm.compiler.llvm.Function) Bitcast(org.robovm.compiler.llvm.Bitcast) Value(org.robovm.compiler.llvm.Value) FunctionRef(org.robovm.compiler.llvm.FunctionRef) Icmp(org.robovm.compiler.llvm.Icmp)

Example 12 with NullConstant

use of org.robovm.compiler.llvm.NullConstant in project robovm by robovm.

the class Linker method createCheckcast.

private Function createCheckcast(ModuleBuilder mb, Clazz clazz, TypeInfo typeInfo) {
    Function fn = FunctionBuilder.checkcast(clazz);
    Value info = getInfoStruct(mb, fn, clazz);
    if (typeInfo.error) {
        // This will trigger an exception
        call(fn, BC_LDC_CLASS, fn.getParameterRef(0), info);
        fn.add(new Ret(new NullConstant(Types.OBJECT_PTR)));
    } else if (!clazz.getClazzInfo().isInterface()) {
        Value result = call(fn, CHECKCAST_CLASS, fn.getParameterRef(0), info, fn.getParameterRef(1), new IntegerConstant((typeInfo.classTypes.length - 1) * 4 + 5 * 4), new IntegerConstant(typeInfo.id));
        fn.add(new Ret(result));
    } else {
        Value result = call(fn, CHECKCAST_INTERFACE, fn.getParameterRef(0), info, fn.getParameterRef(1), new IntegerConstant(typeInfo.id));
        fn.add(new Ret(result));
    }
    return fn;
}
Also used : Ret(org.robovm.compiler.llvm.Ret) ModifiedUtf8HashFunction(org.robovm.compiler.hash.ModifiedUtf8HashFunction) Function(org.robovm.compiler.llvm.Function) Value(org.robovm.compiler.llvm.Value) NullConstant(org.robovm.compiler.llvm.NullConstant) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant)

Example 13 with NullConstant

use of org.robovm.compiler.llvm.NullConstant in project robovm by robovm.

the class ClassCompiler method createClassInfoStruct.

private StructureConstant createClassInfoStruct() {
    int flags = 0;
    if (Modifier.isPublic(sootClass.getModifiers())) {
        flags |= CI_PUBLIC;
    }
    if (Modifier.isFinal(sootClass.getModifiers())) {
        flags |= CI_FINAL;
    }
    if (Modifier.isInterface(sootClass.getModifiers())) {
        flags |= CI_INTERFACE;
    }
    if (Modifier.isAbstract(sootClass.getModifiers())) {
        flags |= CI_ABSTRACT;
    }
    if ((sootClass.getModifiers() & 0x1000) > 0) {
        flags |= CI_SYNTHETIC;
    }
    if (Modifier.isAnnotation(sootClass.getModifiers())) {
        flags |= CI_ANNOTATION;
    }
    if (Modifier.isEnum(sootClass.getModifiers())) {
        flags |= CI_ENUM;
    }
    if (attributesEncoder.classHasAttributes()) {
        flags |= CI_ATTRIBUTES;
    }
    if (hasFinalizer(sootClass)) {
        flags |= CI_FINALIZABLE;
    }
    // Create the ClassInfoHeader structure.
    StructureConstantBuilder header = new StructureConstantBuilder();
    // Points to the runtime Class struct
    header.add(new NullConstant(I8_PTR));
    header.add(new IntegerConstant(flags));
    header.add(getString(getInternalName(sootClass)));
    if (sootClass.declaresMethod("<clinit>", Collections.emptyList(), VoidType.v())) {
        SootMethod method = sootClass.getMethod("<clinit>", Collections.emptyList(), VoidType.v());
        header.add(new FunctionRef(Symbols.methodSymbol(method), getFunctionType(method)));
    } else {
        header.add(new NullConstant(I8_PTR));
    }
    mb.addGlobal(new Global(Symbols.typeInfoSymbol(getInternalName(sootClass)), Linkage.external, I8_PTR, true));
    // TypeInfo* generated by Linker
    header.add(new GlobalRef(Symbols.typeInfoSymbol(getInternalName(sootClass)), I8_PTR));
    if (!sootClass.isInterface()) {
        header.add(createVTableStruct());
    } else {
        header.add(createITableStruct());
    }
    header.add(createITablesStruct());
    header.add(sizeof(classType));
    header.add(sizeof(instanceType));
    if (!instanceFields.isEmpty()) {
        header.add(offsetof(instanceType, 1, 1));
    } else {
        header.add(sizeof(instanceType));
    }
    header.add(new IntegerConstant((short) countReferences(classFields)));
    header.add(new IntegerConstant((short) countReferences(instanceFields)));
    PackedStructureConstantBuilder body = new PackedStructureConstantBuilder();
    body.add(new IntegerConstant((short) sootClass.getInterfaceCount()));
    body.add(new IntegerConstant((short) sootClass.getFieldCount()));
    body.add(new IntegerConstant((short) sootClass.getMethodCount()));
    if (!sootClass.isInterface()) {
        body.add(getStringOrNull(sootClass.hasSuperclass() ? getInternalName(sootClass.getSuperclass()) : null));
    }
    if (attributesEncoder.classHasAttributes()) {
        body.add(new ConstantBitcast(attributesEncoder.getClassAttributes().ref(), I8_PTR));
    }
    for (SootClass s : sootClass.getInterfaces()) {
        body.add(getString(getInternalName(s)));
    }
    for (SootField f : sootClass.getFields()) {
        flags = 0;
        soot.Type t = f.getType();
        if (t instanceof PrimType) {
            if (t.equals(BooleanType.v())) {
                flags |= DESC_Z;
            } else if (t.equals(ByteType.v())) {
                flags |= DESC_B;
            } else if (t.equals(ShortType.v())) {
                flags |= DESC_S;
            } else if (t.equals(CharType.v())) {
                flags |= DESC_C;
            } else if (t.equals(IntType.v())) {
                flags |= DESC_I;
            } else if (t.equals(LongType.v())) {
                flags |= DESC_J;
            } else if (t.equals(FloatType.v())) {
                flags |= DESC_F;
            } else if (t.equals(DoubleType.v())) {
                flags |= DESC_D;
            }
            flags <<= 12;
        }
        if (Modifier.isPublic(f.getModifiers())) {
            flags |= FI_PUBLIC;
        } else if (Modifier.isPrivate(f.getModifiers())) {
            flags |= FI_PRIVATE;
        } else if (Modifier.isProtected(f.getModifiers())) {
            flags |= FI_PROTECTED;
        }
        if (Modifier.isStatic(f.getModifiers())) {
            flags |= FI_STATIC;
        }
        if (Modifier.isFinal(f.getModifiers())) {
            flags |= FI_FINAL;
        }
        if (Modifier.isVolatile(f.getModifiers())) {
            flags |= FI_VOLATILE;
        }
        if (Modifier.isTransient(f.getModifiers())) {
            flags |= FI_TRANSIENT;
        }
        if ((f.getModifiers() & 0x1000) > 0) {
            flags |= FI_SYNTHETIC;
        }
        if (Modifier.isEnum(f.getModifiers())) {
            flags |= FI_ENUM;
        }
        if (attributesEncoder.fieldHasAttributes(f)) {
            flags |= FI_ATTRIBUTES;
        }
        body.add(new IntegerConstant((short) flags));
        body.add(getString(f.getName()));
        if (!(t instanceof PrimType)) {
            body.add(getString(getDescriptor(f)));
        }
        if (f.isStatic()) {
            int index = classFields.indexOf(f);
            body.add(offsetof(classType, 1, index, 1));
        } else {
            int index = instanceFields.indexOf(f);
            body.add(offsetof(instanceType, 1, 1 + index, 1));
        }
        if (attributesEncoder.fieldHasAttributes(f)) {
            body.add(new ConstantBitcast(attributesEncoder.getFieldAttributes(f).ref(), I8_PTR));
        }
    }
    VTable vtable = !sootClass.isInterface() ? config.getVTableCache().get(sootClass) : null;
    ITable itable = sootClass.isInterface() ? config.getITableCache().get(sootClass) : null;
    ;
    for (SootMethod m : sootClass.getMethods()) {
        soot.Type t = m.getReturnType();
        flags = 0;
        if (Modifier.isPublic(m.getModifiers())) {
            flags |= MI_PUBLIC;
        } else if (Modifier.isPrivate(m.getModifiers())) {
            flags |= MI_PRIVATE;
        } else if (Modifier.isProtected(m.getModifiers())) {
            flags |= MI_PROTECTED;
        }
        if (Modifier.isStatic(m.getModifiers())) {
            flags |= MI_STATIC;
        }
        if (Modifier.isFinal(m.getModifiers())) {
            flags |= MI_FINAL;
        }
        if (Modifier.isSynchronized(m.getModifiers())) {
            flags |= MI_SYNCHRONIZED;
        }
        if ((m.getModifiers() & 0x0040) > 0) {
            flags |= MI_BRIDGE;
        }
        if ((m.getModifiers() & 0x0080) > 0) {
            flags |= MI_VARARGS;
        }
        if (Modifier.isNative(m.getModifiers())) {
            if (!isStruct(sootClass) && !hasStructMemberAnnotation(m)) {
                flags |= MI_NATIVE;
            }
        }
        if (Modifier.isAbstract(m.getModifiers())) {
            flags |= MI_ABSTRACT;
        }
        if (Modifier.isStrictFP(m.getModifiers())) {
            flags |= MI_STRICT;
        }
        if ((m.getModifiers() & 0x1000) > 0) {
            flags |= MI_SYNTHETIC;
        }
        if (attributesEncoder.methodHasAttributes(m)) {
            flags |= MI_ATTRIBUTES;
        }
        if (hasBridgeAnnotation(m) || hasGlobalValueAnnotation(m)) {
            flags |= MI_BRO_BRIDGE;
        }
        if (hasCallbackAnnotation(m)) {
            flags |= MI_BRO_CALLBACK;
        }
        if ((t instanceof PrimType || t == VoidType.v()) && m.getParameterCount() == 0) {
            flags |= MI_COMPACT_DESC;
        }
        body.add(new IntegerConstant((short) flags));
        Constant viTableIndex = new IntegerConstant((short) -1);
        if (vtable != null) {
            VTable.Entry entry = vtable.getEntry(m);
            if (entry != null) {
                viTableIndex = new IntegerConstant((short) entry.getIndex());
            }
        } else {
            ITable.Entry entry = itable.getEntry(m);
            if (entry != null) {
                viTableIndex = new IntegerConstant((short) entry.getIndex());
            }
        }
        body.add(viTableIndex);
        body.add(getString(m.getName()));
        if ((flags & MI_COMPACT_DESC) > 0) {
            int desc = 0;
            if (t.equals(BooleanType.v())) {
                desc = DESC_Z;
            } else if (t.equals(ByteType.v())) {
                desc = DESC_B;
            } else if (t.equals(ShortType.v())) {
                desc = DESC_S;
            } else if (t.equals(CharType.v())) {
                desc = DESC_C;
            } else if (t.equals(IntType.v())) {
                desc = DESC_I;
            } else if (t.equals(LongType.v())) {
                desc = DESC_J;
            } else if (t.equals(FloatType.v())) {
                desc = DESC_F;
            } else if (t.equals(DoubleType.v())) {
                desc = DESC_D;
            } else if (t.equals(VoidType.v())) {
                desc = DESC_V;
            }
            body.add(new IntegerConstant((byte) desc));
        } else {
            body.add(getString(getDescriptor(m)));
        }
        if (attributesEncoder.methodHasAttributes(m)) {
            body.add(new ConstantBitcast(attributesEncoder.getMethodAttributes(m).ref(), I8_PTR));
        }
        if (!m.isAbstract()) {
            body.add(new ConstantBitcast(new FunctionRef(Symbols.methodSymbol(m), getFunctionType(m)), I8_PTR));
            // Size of function. This value will be modified later by patching the .s file.
            body.add(new IntegerConstant(DUMMY_METHOD_SIZE));
            if (m.isSynchronized()) {
                body.add(new ConstantBitcast(new FunctionRef(Symbols.synchronizedWrapperSymbol(m), getFunctionType(m)), I8_PTR));
            }
            if ((flags & MI_NATIVE) == 0) {
                // Cannot use m.isNative() in the condition above since methods which are native in the
                // Java class file may have been changed to non-native by the RoboVM compiler 
                // (e.g. @StructMember methods). The native code which parses the info structs will see 
                // the method as non-native.
                // Add a weak linetable pointer which points to a -1 value which will be interpreted as 0 linenumbers in the table
                Global linetableGlobal = new Global(Symbols.linetableSymbol(m), Linkage.weak, new IntegerConstant(-1));
                mb.addGlobal(linetableGlobal);
                body.add(linetableGlobal.ref());
            }
        }
        if (hasBridgeAnnotation(m)) {
            if (!readBooleanElem(getAnnotation(m, BRIDGE), "dynamic", false)) {
                body.add(new GlobalRef(Symbols.bridgePtrSymbol(m), I8_PTR));
            } else {
                body.add(new NullConstant(I8_PTR));
            }
        } else if (hasGlobalValueAnnotation(m)) {
            body.add(new GlobalRef(Symbols.globalValuePtrSymbol(m), I8_PTR));
        }
        if (hasCallbackAnnotation(m)) {
            body.add(new AliasRef(Symbols.callbackPtrSymbol(m), I8_PTR));
        }
    }
    // after sizeof(ClassInfoHeader) bytes.
    return new StructureConstantBuilder().add(header.build()).add(body.build()).build();
}
Also used : GlobalRef(org.robovm.compiler.llvm.GlobalRef) PackedStructureConstantBuilder(org.robovm.compiler.llvm.PackedStructureConstantBuilder) AliasRef(org.robovm.compiler.llvm.AliasRef) StructureConstant(org.robovm.compiler.llvm.StructureConstant) Constant(org.robovm.compiler.llvm.Constant) NullConstant(org.robovm.compiler.llvm.NullConstant) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant) ConstantBitcast(org.robovm.compiler.llvm.ConstantBitcast) NullConstant(org.robovm.compiler.llvm.NullConstant) SootClass(soot.SootClass) StructureConstantBuilder(org.robovm.compiler.llvm.StructureConstantBuilder) PackedStructureConstantBuilder(org.robovm.compiler.llvm.PackedStructureConstantBuilder) IntegerConstant(org.robovm.compiler.llvm.IntegerConstant) Global(org.robovm.compiler.llvm.Global) SootMethod(soot.SootMethod) PrimType(soot.PrimType) SootField(soot.SootField) FunctionRef(org.robovm.compiler.llvm.FunctionRef)

Aggregations

NullConstant (org.robovm.compiler.llvm.NullConstant)13 IntegerConstant (org.robovm.compiler.llvm.IntegerConstant)10 Global (org.robovm.compiler.llvm.Global)9 Function (org.robovm.compiler.llvm.Function)7 FunctionRef (org.robovm.compiler.llvm.FunctionRef)7 FunctionType (org.robovm.compiler.llvm.FunctionType)7 Ret (org.robovm.compiler.llvm.Ret)7 Value (org.robovm.compiler.llvm.Value)7 ConstantBitcast (org.robovm.compiler.llvm.ConstantBitcast)6 PointerType (org.robovm.compiler.llvm.PointerType)6 StructureConstantBuilder (org.robovm.compiler.llvm.StructureConstantBuilder)5 Variable (org.robovm.compiler.llvm.Variable)5 ArrayList (java.util.ArrayList)4 Br (org.robovm.compiler.llvm.Br)4 Label (org.robovm.compiler.llvm.Label)4 Type (org.robovm.compiler.llvm.Type)4 HashSet (java.util.HashSet)3 Bitcast (org.robovm.compiler.llvm.Bitcast)3 Constant (org.robovm.compiler.llvm.Constant)3 FloatingPointType (org.robovm.compiler.llvm.FloatingPointType)3