Search in sources :

Example 1 with FloatConvertNode

use of org.graalvm.compiler.nodes.calc.FloatConvertNode in project graal by oracle.

the class JNIJavaCallWrapperMethod method loadAndUnboxArguments.

private List<Pair<ValueNode, ResolvedJavaType>> loadAndUnboxArguments(JNIGraphKit kit, HostedProviders providers, ResolvedJavaMethod invokeMethod, Signature invokeSignature) {
    MetaAccessProvider metaAccess = providers.getMetaAccess();
    List<Pair<ValueNode, ResolvedJavaType>> args = new ArrayList<>();
    int javaIndex = 0;
    javaIndex += metaAccess.lookupJavaType(JNIEnvironment.class).getJavaKind().getSlotCount();
    if (!invokeMethod.isStatic()) {
        JavaKind kind = metaAccess.lookupJavaType(JNIObjectHandle.class).getJavaKind();
        ValueNode handle = kit.loadLocal(javaIndex, kind);
        ValueNode unboxed = kit.unboxHandle(handle);
        ValueNode receiver;
        ResolvedJavaType receiverClass = invokeMethod.getDeclaringClass();
        if (invokeMethod.isConstructor()) {
            /*
                 * Our target method is a constructor and we might be called via `NewObject`, in
                 * which case we need to allocate the object before calling the constructor. We can
                 * detect when this is the case because unlike with `Call<Type>Method`, we are
                 * passed the object hub of our target class in place of the receiver object.
                 */
            Constant hub = providers.getConstantReflection().asObjectHub(receiverClass);
            ConstantNode hubNode = kit.createConstant(hub, JavaKind.Object);
            kit.startIf(kit.unique(new ObjectEqualsNode(unboxed, hubNode)), BranchProbabilityNode.FAST_PATH_PROBABILITY);
            kit.thenPart();
            ValueNode created = kit.append(new NewInstanceNode(receiverClass, true));
            AbstractMergeNode merge = kit.endIf();
            receiver = kit.unique(new ValuePhiNode(StampFactory.object(), merge, new ValueNode[] { created, unboxed }));
        } else {
            receiver = unboxed;
        }
        args.add(Pair.create(receiver, receiverClass));
    }
    javaIndex += metaAccess.lookupJavaType(JNIObjectHandle.class).getJavaKind().getSlotCount();
    if (nonVirtual) {
        javaIndex += metaAccess.lookupJavaType(JNIObjectHandle.class).getJavaKind().getSlotCount();
    }
    javaIndex += metaAccess.lookupJavaType(JNIMethodId.class).getJavaKind().getSlotCount();
    int count = invokeSignature.getParameterCount(false);
    if (callVariant == CallVariant.VARARGS) {
        for (int i = 0; i < count; i++) {
            ResolvedJavaType type = (ResolvedJavaType) invokeSignature.getParameterType(i, null);
            JavaKind kind = type.getJavaKind();
            JavaKind loadKind = kind;
            if (loadKind == JavaKind.Float) {
                // C varargs promote float to double
                loadKind = JavaKind.Double;
            }
            ValueNode value = kit.loadLocal(javaIndex, loadKind);
            if (kind == JavaKind.Float) {
                value = kit.unique(new FloatConvertNode(FloatConvert.D2F, value));
            } else if (kind.isObject()) {
                value = kit.unboxHandle(value);
            }
            args.add(Pair.create(value, type));
            javaIndex += loadKind.getSlotCount();
        }
    } else if (callVariant == CallVariant.ARRAY) {
        ResolvedJavaType elementType = metaAccess.lookupJavaType(JNIValue.class);
        int elementSize = SizeOf.get(JNIValue.class);
        ValueNode array = kit.loadLocal(javaIndex, elementType.getJavaKind());
        for (int i = 0; i < count; i++) {
            ResolvedJavaType type = (ResolvedJavaType) invokeSignature.getParameterType(i, null);
            JavaKind readKind = type.getJavaKind();
            StructFieldInfo fieldInfo = getJNIValueOffsetOf(elementType, readKind);
            int offset = i * elementSize + fieldInfo.getOffsetInfo().getProperty();
            ConstantNode offsetConstant = kit.createConstant(JavaConstant.forInt(offset), providers.getWordTypes().getWordKind());
            OffsetAddressNode address = kit.unique(new OffsetAddressNode(array, offsetConstant));
            LocationIdentity locationIdentity = fieldInfo.getLocationIdentity();
            if (locationIdentity == null) {
                locationIdentity = LocationIdentity.any();
            }
            Stamp readStamp = getNarrowStamp(providers, readKind);
            ValueNode value = kit.append(new CInterfaceReadNode(address, locationIdentity, readStamp, BarrierType.NONE, "args[" + i + "]"));
            JavaKind stackKind = readKind.getStackKind();
            if (readKind != stackKind) {
                assert stackKind.getBitCount() > readKind.getBitCount() : "read kind must be narrower than stack kind";
                if (readKind.isUnsigned()) {
                    // needed or another op may illegally sign-extend
                    value = kit.unique(new ZeroExtendNode(value, stackKind.getBitCount()));
                } else {
                    value = kit.unique(new SignExtendNode(value, stackKind.getBitCount()));
                }
            } else if (readKind.isObject()) {
                value = kit.unboxHandle(value);
            }
            args.add(Pair.create(value, type));
        }
    } else if (callVariant == CallVariant.VA_LIST) {
        ValueNode valist = kit.loadLocal(javaIndex, metaAccess.lookupJavaType(WordBase.class).getJavaKind());
        for (int i = 0; i < count; i++) {
            ResolvedJavaType type = (ResolvedJavaType) invokeSignature.getParameterType(i, null);
            JavaKind loadKind = type.getJavaKind();
            if (loadKind.isObject()) {
                loadKind = providers.getWordTypes().getWordKind();
            }
            ValueNode value = kit.append(new VaListNextArgNode(loadKind, valist));
            if (type.getJavaKind().isObject()) {
                value = kit.unboxHandle(value);
            }
            args.add(Pair.create(value, type));
        }
    } else {
        throw VMError.unsupportedFeature("Call variant: " + callVariant);
    }
    return args;
}
Also used : NewInstanceNode(org.graalvm.compiler.nodes.java.NewInstanceNode) SignExtendNode(org.graalvm.compiler.nodes.calc.SignExtendNode) Constant(jdk.vm.ci.meta.Constant) JavaConstant(jdk.vm.ci.meta.JavaConstant) ValuePhiNode(org.graalvm.compiler.nodes.ValuePhiNode) CInterfaceReadNode(com.oracle.svm.core.graal.nodes.CInterfaceReadNode) ArrayList(java.util.ArrayList) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) LogicConstantNode(org.graalvm.compiler.nodes.LogicConstantNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) JNIValue(com.oracle.svm.jni.nativeapi.JNIValue) LocationIdentity(org.graalvm.word.LocationIdentity) JNIObjectHandle(com.oracle.svm.jni.nativeapi.JNIObjectHandle) Pair(org.graalvm.collections.Pair) JavaKind(jdk.vm.ci.meta.JavaKind) VaListNextArgNode(com.oracle.svm.core.graal.nodes.VaListNextArgNode) Stamp(org.graalvm.compiler.core.common.type.Stamp) ObjectEqualsNode(org.graalvm.compiler.nodes.calc.ObjectEqualsNode) StructFieldInfo(com.oracle.svm.hosted.c.info.StructFieldInfo) AbstractMergeNode(org.graalvm.compiler.nodes.AbstractMergeNode) ZeroExtendNode(org.graalvm.compiler.nodes.calc.ZeroExtendNode) JNIMethodId(com.oracle.svm.jni.nativeapi.JNIMethodId) FloatConvertNode(org.graalvm.compiler.nodes.calc.FloatConvertNode) OffsetAddressNode(org.graalvm.compiler.nodes.memory.address.OffsetAddressNode) JNIEnvironment(com.oracle.svm.jni.nativeapi.JNIEnvironment) ValueNode(org.graalvm.compiler.nodes.ValueNode) MetaAccessProvider(jdk.vm.ci.meta.MetaAccessProvider)

Example 2 with FloatConvertNode

use of org.graalvm.compiler.nodes.calc.FloatConvertNode in project graal by oracle.

the class CInterfaceInvocationPlugin method adaptPrimitiveType.

static ValueNode adaptPrimitiveType(StructuredGraph graph, ValueNode value, JavaKind fromKind, JavaKind toKind, boolean isUnsigned) {
    if (fromKind == toKind) {
        return value;
    }
    assert fromKind.isNumericFloat() == toKind.isNumericFloat();
    int fromBits = fromKind.getBitCount();
    int toBits = toKind.getBitCount();
    if (fromBits == toBits) {
        return value;
    } else if (fromKind.isNumericFloat()) {
        FloatConvert op;
        if (fromKind == JavaKind.Float && toKind == JavaKind.Double) {
            op = FloatConvert.F2D;
        } else if (fromKind == JavaKind.Double && toKind == JavaKind.Float) {
            op = FloatConvert.D2F;
        } else {
            throw shouldNotReachHere();
        }
        return graph.unique(new FloatConvertNode(op, value));
    } else if (toKind == JavaKind.Boolean) {
        JavaKind computeKind = fromKind == JavaKind.Long ? JavaKind.Long : JavaKind.Int;
        LogicNode comparison = graph.unique(new IntegerEqualsNode(adaptPrimitiveType(graph, value, fromKind, computeKind, true), ConstantNode.forIntegerKind(computeKind, 0, graph)));
        return graph.unique(new ConditionalNode(comparison, ConstantNode.forBoolean(false, graph), ConstantNode.forBoolean(true, graph)));
    } else if (fromBits > toBits) {
        return graph.unique(new NarrowNode(value, toBits));
    } else if (isUnsigned) {
        return graph.unique(new ZeroExtendNode(value, toBits));
    } else {
        return graph.unique(new SignExtendNode(value, toBits));
    }
}
Also used : ConditionalNode(org.graalvm.compiler.nodes.calc.ConditionalNode) FloatConvertNode(org.graalvm.compiler.nodes.calc.FloatConvertNode) IntegerEqualsNode(org.graalvm.compiler.nodes.calc.IntegerEqualsNode) SignExtendNode(org.graalvm.compiler.nodes.calc.SignExtendNode) FloatConvert(org.graalvm.compiler.core.common.calc.FloatConvert) LogicNode(org.graalvm.compiler.nodes.LogicNode) NarrowNode(org.graalvm.compiler.nodes.calc.NarrowNode) ZeroExtendNode(org.graalvm.compiler.nodes.calc.ZeroExtendNode) JavaKind(jdk.vm.ci.meta.JavaKind)

Example 3 with FloatConvertNode

use of org.graalvm.compiler.nodes.calc.FloatConvertNode in project graal by oracle.

the class CEntryPointCallStubMethod method inlinePrologueAndEpilogue.

private static void inlinePrologueAndEpilogue(SubstrateGraphKit kit, InvokeNode prologueInvoke, InvokeNode epilogueInvoke, JavaKind returnKind) {
    assert (prologueInvoke != null) == (epilogueInvoke != null);
    if (prologueInvoke != null) {
        kit.inline(prologueInvoke);
        NodeIterable<CEntryPointPrologueBailoutNode> bailoutNodes = kit.getGraph().getNodes().filter(CEntryPointPrologueBailoutNode.class);
        for (CEntryPointPrologueBailoutNode node : bailoutNodes) {
            ValueNode result = node.getResult();
            switch(returnKind) {
                case Float:
                    assert result.getStackKind().isNumericFloat();
                    result = kit.unique(new FloatConvertNode(FloatConvert.D2F, result));
                    break;
                case Byte:
                case Char:
                case Short:
                case Int:
                    assert result.getStackKind().isNumericInteger();
                    result = kit.unique(new NarrowNode(result, returnKind.getBitCount()));
                    break;
                default:
                    // no conversion necessary
                    break;
            }
            ReturnNode returnNode = kit.add(new ReturnNode(result));
            node.replaceAndDelete(returnNode);
        }
        if (epilogueInvoke.isAlive()) {
            kit.inline(epilogueInvoke);
        }
    }
}
Also used : ReturnNode(org.graalvm.compiler.nodes.ReturnNode) CEntryPointPrologueBailoutNode(com.oracle.svm.core.graal.nodes.CEntryPointPrologueBailoutNode) FloatConvertNode(org.graalvm.compiler.nodes.calc.FloatConvertNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) NarrowNode(org.graalvm.compiler.nodes.calc.NarrowNode)

Example 4 with FloatConvertNode

use of org.graalvm.compiler.nodes.calc.FloatConvertNode in project graal by oracle.

the class CEntryPointCallStubMethod method generateExceptionHandler.

private void generateExceptionHandler(HostedProviders providers, SubstrateGraphKit kit, ExceptionObjectNode exception, JavaKind returnKind) {
    if (entryPointData.getExceptionHandler() == CEntryPointOptions.FatalExceptionHandler.class) {
        kit.append(new CEntryPointLeaveNode(LeaveAction.ExceptionAbort, exception));
        kit.append(new DeadEndNode());
    } else {
        ResolvedJavaType throwable = providers.getMetaAccess().lookupJavaType(Throwable.class);
        ResolvedJavaType handler = providers.getMetaAccess().lookupJavaType(entryPointData.getExceptionHandler());
        ResolvedJavaMethod[] handlerMethods = handler.getDeclaredMethods();
        UserError.guarantee(handlerMethods.length == 1 && handlerMethods[0].isStatic(), "Exception handler class must declare exactly one static method: " + targetMethod.format("%H.%n(%p)") + " -> " + handler.toJavaName());
        JavaType[] handlerParameterTypes = handlerMethods[0].toParameterTypes();
        UserError.guarantee(handlerParameterTypes.length == 1 && ((ResolvedJavaType) handlerParameterTypes[0]).isAssignableFrom(throwable), "Exception handler method must have exactly one parameter of type Throwable: " + targetMethod.format("%H.%n(%p)") + " -> " + handlerMethods[0].format("%H.%n(%p)"));
        int handlerExceptionBci = kit.bci();
        InvokeWithExceptionNode handlerInvoke = kit.startInvokeWithException(handlerMethods[0], InvokeKind.Static, kit.getFrameState(), kit.bci(), handlerExceptionBci, exception);
        kit.noExceptionPart();
        ValueNode returnValue = handlerInvoke;
        if (handlerInvoke.getStackKind() != returnKind) {
            JavaKind fromKind = handlerInvoke.getStackKind();
            if (fromKind == JavaKind.Float && returnKind == JavaKind.Double) {
                returnValue = kit.unique(new FloatConvertNode(FloatConvert.F2D, returnValue));
            } else if (fromKind.isUnsigned() && returnKind.isNumericInteger() && returnKind.getBitCount() > fromKind.getBitCount()) {
                returnValue = kit.unique(new ZeroExtendNode(returnValue, returnKind.getBitCount()));
            } else if (fromKind.isNumericInteger() && returnKind.isNumericInteger() && returnKind.getBitCount() > fromKind.getBitCount()) {
                returnValue = kit.unique(new SignExtendNode(returnValue, returnKind.getBitCount()));
            } else {
                throw UserError.abort("Exception handler method return type must be assignable to entry point method return type: " + targetMethod.format("%H.%n(%p)") + " -> " + handlerMethods[0].format("%H.%n(%p)"));
            }
        }
        kit.createReturn(returnValue, returnValue.getStackKind());
        // fail-safe for exceptions in exception handler
        kit.exceptionPart();
        kit.append(new CEntryPointLeaveNode(LeaveAction.ExceptionAbort, kit.exceptionObject()));
        kit.append(new DeadEndNode());
        kit.endInvokeWithException();
    }
}
Also used : CEntryPointOptions(com.oracle.svm.core.c.function.CEntryPointOptions) SignExtendNode(org.graalvm.compiler.nodes.calc.SignExtendNode) ZeroExtendNode(org.graalvm.compiler.nodes.calc.ZeroExtendNode) CEntryPointLeaveNode(com.oracle.svm.core.graal.nodes.CEntryPointLeaveNode) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) CEntryPoint(org.graalvm.nativeimage.c.function.CEntryPoint) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) JavaType(jdk.vm.ci.meta.JavaType) FloatConvertNode(org.graalvm.compiler.nodes.calc.FloatConvertNode) InvokeWithExceptionNode(org.graalvm.compiler.nodes.InvokeWithExceptionNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) ResolvedJavaMethod(jdk.vm.ci.meta.ResolvedJavaMethod) DeadEndNode(com.oracle.svm.core.graal.nodes.DeadEndNode) JavaKind(jdk.vm.ci.meta.JavaKind)

Aggregations

FloatConvertNode (org.graalvm.compiler.nodes.calc.FloatConvertNode)4 JavaKind (jdk.vm.ci.meta.JavaKind)3 ValueNode (org.graalvm.compiler.nodes.ValueNode)3 SignExtendNode (org.graalvm.compiler.nodes.calc.SignExtendNode)3 ZeroExtendNode (org.graalvm.compiler.nodes.calc.ZeroExtendNode)3 ResolvedJavaType (jdk.vm.ci.meta.ResolvedJavaType)2 NarrowNode (org.graalvm.compiler.nodes.calc.NarrowNode)2 CEntryPointOptions (com.oracle.svm.core.c.function.CEntryPointOptions)1 CEntryPointLeaveNode (com.oracle.svm.core.graal.nodes.CEntryPointLeaveNode)1 CEntryPointPrologueBailoutNode (com.oracle.svm.core.graal.nodes.CEntryPointPrologueBailoutNode)1 CInterfaceReadNode (com.oracle.svm.core.graal.nodes.CInterfaceReadNode)1 DeadEndNode (com.oracle.svm.core.graal.nodes.DeadEndNode)1 VaListNextArgNode (com.oracle.svm.core.graal.nodes.VaListNextArgNode)1 StructFieldInfo (com.oracle.svm.hosted.c.info.StructFieldInfo)1 JNIEnvironment (com.oracle.svm.jni.nativeapi.JNIEnvironment)1 JNIMethodId (com.oracle.svm.jni.nativeapi.JNIMethodId)1 JNIObjectHandle (com.oracle.svm.jni.nativeapi.JNIObjectHandle)1 JNIValue (com.oracle.svm.jni.nativeapi.JNIValue)1 ArrayList (java.util.ArrayList)1 Constant (jdk.vm.ci.meta.Constant)1