Search in sources :

Example 1 with IsNullNode

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

the class GuardPrioritiesTest method unknownTest.

@Test
public void unknownTest() {
    assumeTrue("GuardPriorities must be turned one", GraalOptions.GuardPriorities.getValue(getInitialOptions()));
    StructuredGraph graph = prepareGraph("unknownCondition");
    new SchedulePhase(SchedulePhase.SchedulingStrategy.EARLIEST_WITH_GUARD_ORDER).apply(graph);
    for (GuardNode g1 : graph.getNodes(GuardNode.TYPE)) {
        for (GuardNode g2 : graph.getNodes(GuardNode.TYPE)) {
            if (g1.getSpeculation().isNull() ^ g2.getSpeculation().isNull()) {
                GuardNode withSpeculation = g1.getSpeculation().isNull() ? g2 : g1;
                GuardNode withoutSpeculation = g1.getSpeculation().isNull() ? g1 : g2;
                if (withoutSpeculation.isNegated() && withoutSpeculation.getCondition() instanceof IsNullNode) {
                    IsNullNode isNullNode = (IsNullNode) withoutSpeculation.getCondition();
                    if (isNullNode.getValue() instanceof ParameterNode && ((ParameterNode) isNullNode.getValue()).index() == 1) {
                        // this is the null check before the speculative guard, it's the only
                        // one that should be above
                        assertOrderedAfterLastSchedule(graph, withoutSpeculation, withSpeculation);
                        continue;
                    }
                }
                assertOrderedAfterLastSchedule(graph, withSpeculation, withoutSpeculation);
            }
        }
    }
}
Also used : SchedulePhase(org.graalvm.compiler.phases.schedule.SchedulePhase) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) ParameterNode(org.graalvm.compiler.nodes.ParameterNode) IsNullNode(org.graalvm.compiler.nodes.calc.IsNullNode) GuardNode(org.graalvm.compiler.nodes.GuardNode) Test(org.junit.Test)

Example 2 with IsNullNode

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

the class IntrinsifyMethodHandlesInvocationPlugin method processInvokeWithMethodHandle.

@SuppressWarnings("try")
private void processInvokeWithMethodHandle(GraphBuilderContext b, BytecodeProvider bytecodeProvider, ResolvedJavaMethod methodHandleMethod, ValueNode[] methodHandleArguments) {
    Plugins graphBuilderPlugins = new Plugins(((ReplacementsImpl) originalProviders.getReplacements()).getGraphBuilderPlugins());
    registerInvocationPlugins(graphBuilderPlugins.getInvocationPlugins(), bytecodeProvider);
    graphBuilderPlugins.prependParameterPlugin(new MethodHandlesParameterPlugin(methodHandleArguments));
    graphBuilderPlugins.clearInlineInvokePlugins();
    graphBuilderPlugins.prependInlineInvokePlugin(new MethodHandlesInlineInvokePlugin());
    graphBuilderPlugins.prependNodePlugin(new MethodHandlePlugin(originalProviders.getConstantReflection().getMethodHandleAccess(), false));
    /* We do all the word type rewriting because parameters to the lambda can be word types. */
    SnippetReflectionProvider originalSnippetReflection = GraalAccess.getOriginalSnippetReflection();
    WordOperationPlugin wordOperationPlugin = new WordOperationPlugin(originalSnippetReflection, new WordTypes(originalProviders.getMetaAccess(), FrameAccess.getWordKind()));
    graphBuilderPlugins.appendInlineInvokePlugin(wordOperationPlugin);
    graphBuilderPlugins.appendTypePlugin(wordOperationPlugin);
    graphBuilderPlugins.appendTypePlugin(new TrustedInterfaceTypePlugin());
    graphBuilderPlugins.appendNodePlugin(wordOperationPlugin);
    GraphBuilderConfiguration graphBuilderConfig = GraphBuilderConfiguration.getSnippetDefault(graphBuilderPlugins);
    GraphBuilderPhase.Instance graphBuilder = new GraphBuilderPhase.Instance(originalProviders.getMetaAccess(), originalProviders.getStampProvider(), originalProviders.getConstantReflection(), originalProviders.getConstantFieldProvider(), graphBuilderConfig, OptimisticOptimizations.NONE, null);
    DebugContext debug = b.getDebug();
    StructuredGraph graph = new StructuredGraph.Builder(b.getOptions(), debug).method(toOriginal(methodHandleMethod)).build();
    try (DebugContext.Scope s = debug.scope("IntrinsifyMethodHandles", graph)) {
        graphBuilder.apply(graph);
        /*
             * We do not care about the improved type information from Pi nodes, so we just delete
             * them to simplify our graph.
             */
        for (PiNode pi : graph.getNodes(PiNode.TYPE)) {
            pi.replaceAndDelete(pi.object());
        }
        /*
             * Support for MethodHandle that adapt the input type to a more generic type, i.e., a
             * MethodHandle that does a dynamic type check on a parameter.
             */
        for (UnaryOpLogicNode node : graph.getNodes().filter(UnaryOpLogicNode.class).filter(v -> v instanceof IsNullNode || v instanceof InstanceOfNode)) {
            ValueNode value = node.getValue();
            if (value instanceof ParameterNode) {
                /*
                     * We just assume that the InstanceOfNode or IsNullNode are used in an If and
                     * the true-successor is actually the branch we want. If that assumption is
                     * wrong, nothing bad happens - we will just continue to report the invocation
                     * as unsupported because the updated stamp for the parameter will not simplify
                     * the graph.
                     */
                if (node instanceof InstanceOfNode) {
                    InstanceOfNode inst = (InstanceOfNode) node;
                    TypeReference typeRef = inst.type();
                    value.setStamp(new ObjectStamp(typeRef.getType(), typeRef.isExact(), !inst.allowsNull(), false));
                } else {
                    assert node instanceof IsNullNode;
                    ResolvedJavaType type = value.stamp(NodeView.DEFAULT).javaType(originalProviders.getMetaAccess());
                    value.setStamp(new ObjectStamp(type, false, /* non-null */
                    true, false));
                }
            }
        }
        /*
             * The canonicalizer converts unsafe field accesses for get/set method handles back to
             * high-level field load and store nodes.
             */
        new CanonicalizerPhase().apply(graph, new PhaseContext(originalProviders));
        for (FixedGuardNode guard : graph.getNodes(FixedGuardNode.TYPE)) {
            if (guard.next() instanceof AccessFieldNode && guard.condition() instanceof IsNullNode && guard.isNegated() && ((IsNullNode) guard.condition()).getValue() == ((AccessFieldNode) guard.next()).object()) {
                /*
                     * Method handles to load and stores fields have null checks. Remove them, since
                     * the null check is implicitly done by the field access.
                     */
                GraphUtil.removeFixedWithUnusedInputs(guard);
            }
        }
        debug.dump(DebugContext.VERY_DETAILED_LEVEL, graph, "Final intrinisfication graph");
        /*
             * After parsing (and recursive inlining during parsing), the graph must contain only
             * one invocation (and therefore only one MethodCallTargetNode), plus the parameters,
             * constants, start, and return nodes.
             */
        Node singleFunctionality = null;
        ReturnNode singleReturn = null;
        for (Node node : graph.getNodes()) {
            if (node == graph.start() || node instanceof ParameterNode || node instanceof ConstantNode || node instanceof FrameState) {
                /* Ignore the allowed framework around the nodes we care about. */
                continue;
            } else if (node instanceof Invoke) {
                /* We check the MethodCallTargetNode, so we can ignore the invoke. */
                continue;
            } else if ((node instanceof MethodCallTargetNode || node instanceof LoadFieldNode || node instanceof StoreFieldNode) && singleFunctionality == null) {
                singleFunctionality = node;
                continue;
            } else if (node instanceof ReturnNode && singleReturn == null) {
                singleReturn = (ReturnNode) node;
                continue;
            }
            throw new UnsupportedFeatureException("Invoke with MethodHandle argument could not be reduced to at most a single call: " + methodHandleMethod.format("%H.%n(%p)"));
        }
        if (singleFunctionality instanceof MethodCallTargetNode) {
            MethodCallTargetNode singleCallTarget = (MethodCallTargetNode) singleFunctionality;
            assert singleReturn.result() == null || singleReturn.result() == singleCallTarget.invoke();
            /*
                 * Replace the originalTarget with the replacementTarget. Note that the
                 * replacementTarget node belongs to a different graph than originalTarget, so we
                 * need to match parameter back to the original graph and allocate a new
                 * MethodCallTargetNode for the original graph.
                 */
            ValueNode[] replacedArguments = new ValueNode[singleCallTarget.arguments().size()];
            for (int i = 0; i < replacedArguments.length; i++) {
                replacedArguments[i] = lookup(b, methodHandleArguments, singleCallTarget.arguments().get(i));
            }
            b.handleReplacedInvoke(singleCallTarget.invokeKind(), lookup(singleCallTarget.targetMethod()), replacedArguments, false);
        } else if (singleFunctionality instanceof LoadFieldNode) {
            LoadFieldNode fieldLoad = (LoadFieldNode) singleFunctionality;
            b.addPush(b.getInvokeReturnType().getJavaKind(), LoadFieldNode.create(null, lookup(b, methodHandleArguments, fieldLoad.object()), lookup(fieldLoad.field())));
        } else if (singleFunctionality instanceof StoreFieldNode) {
            StoreFieldNode fieldStore = (StoreFieldNode) singleFunctionality;
            b.add(new StoreFieldNode(lookup(b, methodHandleArguments, fieldStore.object()), lookup(fieldStore.field()), lookup(b, methodHandleArguments, fieldStore.value())));
        } else if (singleReturn.result() != null) {
            /* Replace the invocation with he constant result. */
            JavaConstant constantResult = singleReturn.result().asJavaConstant();
            assert b.getInvokeReturnType().getJavaKind() == constantResult.getJavaKind();
            b.addPush(constantResult.getJavaKind(), ConstantNode.forConstant(lookup(constantResult), universeProviders.getMetaAccess()));
        } else {
            /* No invoke and no return value, so nothing to do. */
            assert b.getInvokeReturnType().getJavaKind() == JavaKind.Void;
        }
    } catch (Throwable ex) {
        throw debug.handle(ex);
    }
}
Also used : ObjectStamp(org.graalvm.compiler.core.common.type.ObjectStamp) MethodCallTargetNode(org.graalvm.compiler.nodes.java.MethodCallTargetNode) AccessFieldNode(org.graalvm.compiler.nodes.java.AccessFieldNode) ReturnNode(org.graalvm.compiler.nodes.ReturnNode) FixedGuardNode(org.graalvm.compiler.nodes.FixedGuardNode) PiNode(org.graalvm.compiler.nodes.PiNode) UnaryOpLogicNode(org.graalvm.compiler.nodes.UnaryOpLogicNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) IsNullNode(org.graalvm.compiler.nodes.calc.IsNullNode) FloatingNode(org.graalvm.compiler.nodes.calc.FloatingNode) LoadFieldNode(org.graalvm.compiler.nodes.java.LoadFieldNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) InstanceOfNode(org.graalvm.compiler.nodes.java.InstanceOfNode) ParameterNode(org.graalvm.compiler.nodes.ParameterNode) StoreFieldNode(org.graalvm.compiler.nodes.java.StoreFieldNode) Node(org.graalvm.compiler.graph.Node) WordTypes(org.graalvm.compiler.word.WordTypes) JavaConstant(jdk.vm.ci.meta.JavaConstant) PiNode(org.graalvm.compiler.nodes.PiNode) FrameState(org.graalvm.compiler.nodes.FrameState) UnaryOpLogicNode(org.graalvm.compiler.nodes.UnaryOpLogicNode) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) Invoke(org.graalvm.compiler.nodes.Invoke) PhaseContext(org.graalvm.compiler.phases.tiers.PhaseContext) SnippetReflectionProvider(org.graalvm.compiler.api.replacements.SnippetReflectionProvider) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) ParameterNode(org.graalvm.compiler.nodes.ParameterNode) TypeReference(org.graalvm.compiler.core.common.type.TypeReference) GraphBuilderPhase(org.graalvm.compiler.java.GraphBuilderPhase) InvocationPlugins(org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins) Plugins(org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins) StoreFieldNode(org.graalvm.compiler.nodes.java.StoreFieldNode) UnsupportedFeatureException(com.oracle.graal.pointsto.constraints.UnsupportedFeatureException) GraphBuilderConfiguration(org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration) DebugContext(org.graalvm.compiler.debug.DebugContext) LoadFieldNode(org.graalvm.compiler.nodes.java.LoadFieldNode) TrustedInterfaceTypePlugin(com.oracle.svm.core.graal.phases.TrustedInterfaceTypePlugin) FixedGuardNode(org.graalvm.compiler.nodes.FixedGuardNode) ReturnNode(org.graalvm.compiler.nodes.ReturnNode) MethodCallTargetNode(org.graalvm.compiler.nodes.java.MethodCallTargetNode) IsNullNode(org.graalvm.compiler.nodes.calc.IsNullNode) AccessFieldNode(org.graalvm.compiler.nodes.java.AccessFieldNode) ValueNode(org.graalvm.compiler.nodes.ValueNode) CanonicalizerPhase(org.graalvm.compiler.phases.common.CanonicalizerPhase) InstanceOfNode(org.graalvm.compiler.nodes.java.InstanceOfNode) MethodHandlePlugin(org.graalvm.compiler.replacements.MethodHandlePlugin) WordOperationPlugin(org.graalvm.compiler.word.WordOperationPlugin)

Example 3 with IsNullNode

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

the class CEntryPointCallStubMethod method adaptReturnValue.

private ValueNode adaptReturnValue(ResolvedJavaMethod method, HostedProviders providers, Purpose purpose, UniverseMetaAccess metaAccess, NativeLibraries nativeLibraries, HostedGraphKit kit, ValueNode invokeValue) {
    ValueNode returnValue = invokeValue;
    if (returnValue.getStackKind().isPrimitive()) {
        return returnValue;
    }
    JavaType returnType = method.getSignature().getReturnType(null);
    ElementInfo typeInfo = nativeLibraries.findElementInfo(returnType);
    if (typeInfo instanceof EnumInfo) {
        UserError.guarantee(typeInfo.getChildren().stream().anyMatch(EnumValueInfo.class::isInstance), "Enum class " + returnType.toJavaName() + " needs a method that is annotated with @" + CEnumValue.class + " because it is used as the return type of an entry point method: " + targetMethod.format("%H.%n(%p)"));
        IsNullNode isNull = kit.unique(new IsNullNode(returnValue));
        kit.startIf(isNull, BranchProbabilityNode.VERY_SLOW_PATH_PROBABILITY);
        kit.thenPart();
        ResolvedJavaType enumExceptionType = metaAccess.lookupJavaType(RuntimeException.class);
        NewInstanceNode enumException = kit.append(new NewInstanceNode(enumExceptionType, true));
        Iterator<ResolvedJavaMethod> enumExceptionCtor = Arrays.stream(enumExceptionType.getDeclaredConstructors()).filter(c -> c.getSignature().getParameterCount(false) == 1 && c.getSignature().getParameterType(0, null).equals(metaAccess.lookupJavaType(String.class))).iterator();
        ConstantNode enumExceptionMessage = kit.createConstant(kit.getConstantReflection().forString("null return value cannot be converted to a C enum value"), JavaKind.Object);
        kit.createJavaCallWithExceptionAndUnwind(InvokeKind.Special, enumExceptionCtor.next(), enumException, enumExceptionMessage);
        assert !enumExceptionCtor.hasNext();
        kit.append(new CEntryPointLeaveNode(LeaveAction.ExceptionAbort, enumException));
        kit.append(new DeadEndNode());
        kit.endIf();
        // Always return enum values as a signed word because it should never be a problem if
        // the caller expects a narrower integer type and the various checks already handle
        // replacements with word types
        CInterfaceEnumTool tool = new CInterfaceEnumTool(providers.getMetaAccess(), providers.getSnippetReflection());
        JavaKind cEnumReturnType = providers.getWordTypes().getWordKind();
        assert !cEnumReturnType.isUnsigned() : "requires correct representation of signed values";
        returnValue = tool.createEnumValueInvoke(kit, (EnumInfo) typeInfo, cEnumReturnType, returnValue);
    } else if (purpose != Purpose.ANALYSIS) {
        // for analysis test cases: abort only during compilation
        throw UserError.abort("Entry point method return types are restricted to primitive types, word types and enumerations (@" + CEnum.class.getSimpleName() + "): " + targetMethod.format("%H.%n(%p)"));
    }
    return returnValue;
}
Also used : Isolate(org.graalvm.nativeimage.Isolate) HostedProviders(com.oracle.graal.pointsto.meta.HostedProviders) Arrays(java.util.Arrays) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) GraphProvider(com.oracle.graal.pointsto.infrastructure.GraphProvider) NativeBootImage(com.oracle.svm.hosted.image.NativeBootImage) Constant(jdk.vm.ci.meta.Constant) CEntryPointOptions(com.oracle.svm.core.c.function.CEntryPointOptions) NarrowNode(org.graalvm.compiler.nodes.calc.NarrowNode) CInterfaceEnumTool(com.oracle.svm.hosted.phases.CInterfaceEnumTool) StampFactory(org.graalvm.compiler.core.common.type.StampFactory) NativeLibraries(com.oracle.svm.hosted.c.NativeLibraries) JavaKind(jdk.vm.ci.meta.JavaKind) IsolateThread(org.graalvm.nativeimage.IsolateThread) UserError(com.oracle.svm.core.util.UserError) SignExtendNode(org.graalvm.compiler.nodes.calc.SignExtendNode) FloatConvertNode(org.graalvm.compiler.nodes.calc.FloatConvertNode) ZeroExtendNode(org.graalvm.compiler.nodes.calc.ZeroExtendNode) EnumInfo(com.oracle.svm.hosted.c.info.EnumInfo) ReturnNode(org.graalvm.compiler.nodes.ReturnNode) CEntryPoint(org.graalvm.nativeimage.c.function.CEntryPoint) CEntryPointPrologueBailoutNode(com.oracle.svm.core.graal.nodes.CEntryPointPrologueBailoutNode) CEntryPointSetup(com.oracle.svm.core.c.function.CEntryPointSetup) CEntryPointLeaveNode(com.oracle.svm.core.graal.nodes.CEntryPointLeaveNode) ElementInfo(com.oracle.svm.hosted.c.info.ElementInfo) ConstantPool(jdk.vm.ci.meta.ConstantPool) CEnumValue(org.graalvm.nativeimage.c.constant.CEnumValue) UniverseMetaAccess(com.oracle.graal.pointsto.infrastructure.UniverseMetaAccess) Uninterruptible(com.oracle.svm.core.annotate.Uninterruptible) VMError(com.oracle.svm.core.util.VMError) ValueNode(org.graalvm.compiler.nodes.ValueNode) JavaType(jdk.vm.ci.meta.JavaType) FrameState(org.graalvm.compiler.nodes.FrameState) Type(java.lang.reflect.Type) NodeIterable(org.graalvm.compiler.graph.iterators.NodeIterable) IsNullNode(org.graalvm.compiler.nodes.calc.IsNullNode) Modifier(java.lang.reflect.Modifier) Annotation(java.lang.annotation.Annotation) NoPrologue(com.oracle.svm.core.c.function.CEntryPointOptions.NoPrologue) NoEpilogue(com.oracle.svm.core.c.function.CEntryPointOptions.NoEpilogue) SpeculationLog(jdk.vm.ci.meta.SpeculationLog) CEnum(org.graalvm.nativeimage.c.constant.CEnum) HostedGraphKit(com.oracle.svm.hosted.phases.HostedGraphKit) MetaAccessProvider(jdk.vm.ci.meta.MetaAccessProvider) Signature(jdk.vm.ci.meta.Signature) BranchProbabilityNode(org.graalvm.compiler.nodes.extended.BranchProbabilityNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) InvokeWithExceptionNode(org.graalvm.compiler.nodes.InvokeWithExceptionNode) WrappedJavaMethod(com.oracle.graal.pointsto.infrastructure.WrappedJavaMethod) ExceptionObjectNode(org.graalvm.compiler.nodes.java.ExceptionObjectNode) InvokeKind(org.graalvm.compiler.nodes.CallTargetNode.InvokeKind) EnumValueInfo(com.oracle.svm.hosted.c.info.EnumValueInfo) DebugContext(org.graalvm.compiler.debug.DebugContext) CEntryPointCallStubs(com.oracle.svm.core.code.CEntryPointCallStubs) EnumLookupInfo(com.oracle.svm.hosted.c.info.EnumLookupInfo) InvokeNode(org.graalvm.compiler.nodes.InvokeNode) AnalysisMetaAccess(com.oracle.graal.pointsto.meta.AnalysisMetaAccess) ParameterNode(org.graalvm.compiler.nodes.ParameterNode) AnalysisMethod(com.oracle.graal.pointsto.meta.AnalysisMethod) Iterator(java.util.Iterator) CEnumLookup(org.graalvm.nativeimage.c.constant.CEnumLookup) ExceptionHandler(jdk.vm.ci.meta.ExceptionHandler) ProfilingInfo(jdk.vm.ci.meta.ProfilingInfo) SubstrateGraphKit(com.oracle.svm.core.graal.replacements.SubstrateGraphKit) FloatConvert(org.graalvm.compiler.core.common.calc.FloatConvert) LineNumberTable(jdk.vm.ci.meta.LineNumberTable) LocalVariableTable(jdk.vm.ci.meta.LocalVariableTable) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) DeadEndNode(com.oracle.svm.core.graal.nodes.DeadEndNode) LeaveAction(com.oracle.svm.core.graal.nodes.CEntryPointLeaveNode.LeaveAction) NewInstanceNode(org.graalvm.compiler.nodes.java.NewInstanceNode) ResolvedJavaMethod(jdk.vm.ci.meta.ResolvedJavaMethod) CEnumValue(org.graalvm.nativeimage.c.constant.CEnumValue) NewInstanceNode(org.graalvm.compiler.nodes.java.NewInstanceNode) ElementInfo(com.oracle.svm.hosted.c.info.ElementInfo) EnumInfo(com.oracle.svm.hosted.c.info.EnumInfo) CEntryPointLeaveNode(com.oracle.svm.core.graal.nodes.CEntryPointLeaveNode) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) JavaType(jdk.vm.ci.meta.JavaType) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) IsNullNode(org.graalvm.compiler.nodes.calc.IsNullNode) CEnum(org.graalvm.nativeimage.c.constant.CEnum) ValueNode(org.graalvm.compiler.nodes.ValueNode) CInterfaceEnumTool(com.oracle.svm.hosted.phases.CInterfaceEnumTool) ResolvedJavaMethod(jdk.vm.ci.meta.ResolvedJavaMethod) DeadEndNode(com.oracle.svm.core.graal.nodes.DeadEndNode) JavaKind(jdk.vm.ci.meta.JavaKind)

Example 4 with IsNullNode

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

the class CFunctionCallStubMethod method adaptSignatureAndConvertArguments.

private static Signature adaptSignatureAndConvertArguments(ResolvedJavaMethod method, HostedProviders providers, NativeLibraries nativeLibraries, HostedGraphKit kit, Signature signature, List<ValueNode> arguments) {
    MetaAccessProvider metaAccess = providers.getMetaAccess();
    JavaType returnType = signature.getReturnType(null);
    JavaType[] parameterTypes = signature.toParameterTypes(null);
    for (int i = 0; i < parameterTypes.length; i++) {
        if (!isPrimitiveOrWord(providers, parameterTypes[i])) {
            ElementInfo typeInfo = nativeLibraries.findElementInfo(parameterTypes[i]);
            if (typeInfo instanceof EnumInfo) {
                UserError.guarantee(typeInfo.getChildren().stream().anyMatch(EnumValueInfo.class::isInstance), "Enum class " + returnType.toJavaName() + " needs a method that is annotated with @" + CEnumValue.class.getSimpleName() + " because it is used as a parameter of a method annotated with @" + CFunction.class.getSimpleName() + ": " + method.format("%H.%n(%p)"));
                ValueNode argumentValue = arguments.get(i);
                IsNullNode isNull = kit.unique(new IsNullNode(argumentValue));
                kit.startIf(isNull, BranchProbabilityNode.VERY_SLOW_PATH_PROBABILITY);
                kit.thenPart();
                ResolvedJavaType enumExceptionType = metaAccess.lookupJavaType(RuntimeException.class);
                NewInstanceNode enumException = kit.append(new NewInstanceNode(enumExceptionType, true));
                Iterator<ResolvedJavaMethod> enumExceptionCtor = Arrays.stream(enumExceptionType.getDeclaredConstructors()).filter(c -> c.getSignature().getParameterCount(false) == 1 && c.getSignature().getParameterType(0, null).equals(metaAccess.lookupJavaType(String.class))).iterator();
                ConstantNode enumExceptionMessage = kit.createConstant(kit.getConstantReflection().forString("null return value cannot be converted to a C enum value"), JavaKind.Object);
                kit.createJavaCallWithExceptionAndUnwind(InvokeKind.Special, enumExceptionCtor.next(), enumException, enumExceptionMessage);
                assert !enumExceptionCtor.hasNext();
                kit.append(new UnwindNode(enumException));
                kit.endIf();
                CInterfaceEnumTool tool = new CInterfaceEnumTool(metaAccess, providers.getSnippetReflection());
                argumentValue = tool.createEnumValueInvoke(kit, (EnumInfo) typeInfo, cEnumKind, argumentValue);
                arguments.set(i, argumentValue);
                parameterTypes[i] = metaAccess.lookupJavaType(cEnumKind.toJavaClass());
            } else {
                throw UserError.abort("@" + CFunction.class.getSimpleName() + " parameter types are restricted to primitive types, word types and enumerations (@" + CEnum.class.getSimpleName() + "): " + method.format("%H.%n(%p)"));
            }
        }
    }
    if (!isPrimitiveOrWord(providers, returnType)) {
        // Assume enum: actual checks and conversion are in adaptReturnValue()
        returnType = providers.getWordTypes().getWordImplType();
    }
    JavaType actualReturnType = returnType;
    return new Signature() {

        @Override
        public int getParameterCount(boolean receiver) {
            return parameterTypes.length;
        }

        @Override
        public JavaType getParameterType(int index, ResolvedJavaType accessingClass) {
            return parameterTypes[index];
        }

        @Override
        public JavaType getReturnType(ResolvedJavaType accessingClass) {
            return actualReturnType;
        }
    };
}
Also used : HostedProviders(com.oracle.graal.pointsto.meta.HostedProviders) Signature(jdk.vm.ci.meta.Signature) Arrays(java.util.Arrays) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) BranchProbabilityNode(org.graalvm.compiler.nodes.extended.BranchProbabilityNode) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) CGlobalDataLoadAddressNode(com.oracle.svm.core.graal.nodes.CGlobalDataLoadAddressNode) InvokeKind(org.graalvm.compiler.nodes.CallTargetNode.InvokeKind) CInterfaceEnumTool(com.oracle.svm.hosted.phases.CInterfaceEnumTool) NativeLibraries(com.oracle.svm.hosted.c.NativeLibraries) EnumValueInfo(com.oracle.svm.hosted.c.info.EnumValueInfo) JavaKind(jdk.vm.ci.meta.JavaKind) Transition(org.graalvm.nativeimage.c.function.CFunction.Transition) DebugContext(org.graalvm.compiler.debug.DebugContext) FrameStateBuilder(org.graalvm.compiler.java.FrameStateBuilder) UserError(com.oracle.svm.core.util.UserError) EnumInfo(com.oracle.svm.hosted.c.info.EnumInfo) ImageSingletons(org.graalvm.nativeimage.ImageSingletons) Iterator(java.util.Iterator) ElementInfo(com.oracle.svm.hosted.c.info.ElementInfo) CustomSubstitutionMethod(com.oracle.svm.hosted.annotation.CustomSubstitutionMethod) CFunction(org.graalvm.nativeimage.c.function.CFunction) SharedMethod(com.oracle.svm.core.meta.SharedMethod) CGlobalDataInfo(com.oracle.svm.core.graal.code.CGlobalDataInfo) CEnumLookup(org.graalvm.nativeimage.c.constant.CEnumLookup) CEnumValue(org.graalvm.nativeimage.c.constant.CEnumValue) ValueNode(org.graalvm.compiler.nodes.ValueNode) JavaType(jdk.vm.ci.meta.JavaType) List(java.util.List) StructuredGraph(org.graalvm.compiler.nodes.StructuredGraph) UnwindNode(org.graalvm.compiler.nodes.UnwindNode) IsNullNode(org.graalvm.compiler.nodes.calc.IsNullNode) NewInstanceNode(org.graalvm.compiler.nodes.java.NewInstanceNode) ResolvedJavaMethod(jdk.vm.ci.meta.ResolvedJavaMethod) CEnum(org.graalvm.nativeimage.c.constant.CEnum) HostedGraphKit(com.oracle.svm.hosted.phases.HostedGraphKit) MetaAccessProvider(jdk.vm.ci.meta.MetaAccessProvider) NewInstanceNode(org.graalvm.compiler.nodes.java.NewInstanceNode) ElementInfo(com.oracle.svm.hosted.c.info.ElementInfo) EnumInfo(com.oracle.svm.hosted.c.info.EnumInfo) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) ResolvedJavaType(jdk.vm.ci.meta.ResolvedJavaType) JavaType(jdk.vm.ci.meta.JavaType) ConstantNode(org.graalvm.compiler.nodes.ConstantNode) IsNullNode(org.graalvm.compiler.nodes.calc.IsNullNode) Signature(jdk.vm.ci.meta.Signature) ValueNode(org.graalvm.compiler.nodes.ValueNode) CInterfaceEnumTool(com.oracle.svm.hosted.phases.CInterfaceEnumTool) UnwindNode(org.graalvm.compiler.nodes.UnwindNode) MetaAccessProvider(jdk.vm.ci.meta.MetaAccessProvider) ResolvedJavaMethod(jdk.vm.ci.meta.ResolvedJavaMethod)

Example 5 with IsNullNode

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

the class NodeLIRBuilder method emitConditional.

public Variable emitConditional(LogicNode node, Value trueValue, Value falseValue) {
    if (node instanceof IsNullNode) {
        IsNullNode isNullNode = (IsNullNode) node;
        LIRKind kind = gen.getLIRKind(isNullNode.getValue().stamp(NodeView.DEFAULT));
        Value nullValue = gen.emitConstant(kind, JavaConstant.NULL_POINTER);
        return gen.emitConditionalMove(kind.getPlatformKind(), operand(isNullNode.getValue()), nullValue, Condition.EQ, false, trueValue, falseValue);
    } else if (node instanceof CompareNode) {
        CompareNode compare = (CompareNode) node;
        PlatformKind kind = gen.getLIRKind(compare.getX().stamp(NodeView.DEFAULT)).getPlatformKind();
        return gen.emitConditionalMove(kind, operand(compare.getX()), operand(compare.getY()), compare.condition().asCondition(), compare.unorderedIsTrue(), trueValue, falseValue);
    } else if (node instanceof LogicConstantNode) {
        return gen.emitMove(((LogicConstantNode) node).getValue() ? trueValue : falseValue);
    } else if (node instanceof IntegerTestNode) {
        IntegerTestNode test = (IntegerTestNode) node;
        return gen.emitIntegerTestMove(operand(test.getX()), operand(test.getY()), trueValue, falseValue);
    } else {
        throw GraalError.unimplemented(node.toString());
    }
}
Also used : CompareNode(org.graalvm.compiler.nodes.calc.CompareNode) IsNullNode(org.graalvm.compiler.nodes.calc.IsNullNode) IntegerTestNode(org.graalvm.compiler.nodes.calc.IntegerTestNode) ComplexMatchValue(org.graalvm.compiler.core.match.ComplexMatchValue) Value(jdk.vm.ci.meta.Value) AllocatableValue(jdk.vm.ci.meta.AllocatableValue) LogicConstantNode(org.graalvm.compiler.nodes.LogicConstantNode) LIRKind(org.graalvm.compiler.core.common.LIRKind) PlatformKind(jdk.vm.ci.meta.PlatformKind)

Aggregations

IsNullNode (org.graalvm.compiler.nodes.calc.IsNullNode)7 ValueNode (org.graalvm.compiler.nodes.ValueNode)5 DebugContext (org.graalvm.compiler.debug.DebugContext)4 StructuredGraph (org.graalvm.compiler.nodes.StructuredGraph)4 ResolvedJavaType (jdk.vm.ci.meta.ResolvedJavaType)3 ConstantNode (org.graalvm.compiler.nodes.ConstantNode)3 ParameterNode (org.graalvm.compiler.nodes.ParameterNode)3 HostedProviders (com.oracle.graal.pointsto.meta.HostedProviders)2 UserError (com.oracle.svm.core.util.UserError)2 NativeLibraries (com.oracle.svm.hosted.c.NativeLibraries)2 ElementInfo (com.oracle.svm.hosted.c.info.ElementInfo)2 EnumInfo (com.oracle.svm.hosted.c.info.EnumInfo)2 EnumValueInfo (com.oracle.svm.hosted.c.info.EnumValueInfo)2 CInterfaceEnumTool (com.oracle.svm.hosted.phases.CInterfaceEnumTool)2 HostedGraphKit (com.oracle.svm.hosted.phases.HostedGraphKit)2 Arrays (java.util.Arrays)2 Iterator (java.util.Iterator)2 JavaKind (jdk.vm.ci.meta.JavaKind)2 JavaType (jdk.vm.ci.meta.JavaType)2 MetaAccessProvider (jdk.vm.ci.meta.MetaAccessProvider)2