Search in sources :

Example 1 with NodeIntrinsic

use of org.graalvm.compiler.graph.Node.NodeIntrinsic in project graal by oracle.

the class NodeIntrinsicVerifier method verify.

@Override
public void verify(Element element, AnnotationMirror annotation, PluginGenerator generator) {
    if (element.getKind() != ElementKind.METHOD) {
        assert false : "Element is guaranteed to be a method.";
        return;
    }
    ExecutableElement intrinsicMethod = (ExecutableElement) element;
    if (!intrinsicMethod.getModifiers().contains(Modifier.STATIC)) {
        env.getMessager().printMessage(Kind.ERROR, String.format("A @%s method must be static.", NodeIntrinsic.class.getSimpleName()), element, annotation);
    }
    if (!intrinsicMethod.getModifiers().contains(Modifier.NATIVE)) {
        env.getMessager().printMessage(Kind.ERROR, String.format("A @%s method must be native.", NodeIntrinsic.class.getSimpleName()), element, annotation);
    }
    TypeMirror nodeClassMirror = resolveAnnotationValue(TypeMirror.class, findAnnotationValue(annotation, NODE_CLASS_NAME));
    TypeElement nodeClass = (TypeElement) env.getTypeUtils().asElement(nodeClassMirror);
    if (nodeClass.getSimpleName().contentEquals(NodeIntrinsic.class.getSimpleName())) {
        // default value
        Element enclosingElement = intrinsicMethod.getEnclosingElement();
        while (enclosingElement != null && enclosingElement.getKind() != ElementKind.CLASS) {
            enclosingElement = enclosingElement.getEnclosingElement();
        }
        if (enclosingElement != null) {
            nodeClass = (TypeElement) enclosingElement;
        }
    }
    TypeMirror returnType = intrinsicMethod.getReturnType();
    if (returnType instanceof TypeVariable) {
        env.getMessager().printMessage(Kind.ERROR, "@NodeIntrinsic cannot have a generic return type.", element, annotation);
    }
    boolean injectedStampIsNonNull = intrinsicMethod.getAnnotation(NodeIntrinsic.class).injectedStampIsNonNull();
    if (returnType.getKind() == TypeKind.VOID) {
        for (VariableElement parameter : intrinsicMethod.getParameters()) {
            if (parameter.getAnnotation(InjectedNodeParameter.class) != null) {
                env.getMessager().printMessage(Kind.ERROR, "@NodeIntrinsic with an injected Stamp parameter cannot have a void return type.", element, annotation);
                break;
            }
        }
    }
    TypeMirror[] constructorSignature = constructorSignature(intrinsicMethod);
    Map<ExecutableElement, String> nonMatches = new HashMap<>();
    List<ExecutableElement> factories = findIntrinsifyFactoryMethod(nodeClass, constructorSignature, nonMatches, injectedStampIsNonNull);
    List<ExecutableElement> constructors = Collections.emptyList();
    if (nodeClass.getModifiers().contains(Modifier.ABSTRACT)) {
        if (factories.isEmpty()) {
            env.getMessager().printMessage(Kind.ERROR, String.format("Cannot make a node intrinsic for an abstract class %s.", nodeClass.getSimpleName()), element, annotation);
        }
    } else if (!isNodeType(nodeClass)) {
        if (factories.isEmpty()) {
            env.getMessager().printMessage(Kind.ERROR, String.format("%s is not a subclass of %s.", nodeClass.getSimpleName(), nodeType()), element, annotation);
        }
    } else {
        TypeMirror ret = returnType;
        if (env.getTypeUtils().isAssignable(ret, structuralInputType())) {
            checkInputType(nodeClass, ret, element, annotation);
        }
        constructors = findConstructors(nodeClass, constructorSignature, nonMatches, injectedStampIsNonNull);
    }
    Formatter msg = new Formatter();
    if (factories.size() > 1) {
        msg.format("Found more than one factory in %s matching node intrinsic:", nodeClass);
        for (ExecutableElement candidate : factories) {
            msg.format("%n  %s", candidate);
        }
        env.getMessager().printMessage(Kind.ERROR, msg.toString(), intrinsicMethod, annotation);
    } else if (constructors.size() > 1) {
        msg.format("Found more than one constructor in %s matching node intrinsic:", nodeClass);
        for (ExecutableElement candidate : constructors) {
            msg.format("%n  %s", candidate);
        }
        env.getMessager().printMessage(Kind.ERROR, msg.toString(), intrinsicMethod, annotation);
    } else if (factories.size() == 1) {
        generator.addPlugin(new GeneratedNodeIntrinsicPlugin.CustomFactoryPlugin(intrinsicMethod, factories.get(0), constructorSignature));
    } else if (constructors.size() == 1) {
        generator.addPlugin(new GeneratedNodeIntrinsicPlugin.ConstructorPlugin(intrinsicMethod, constructors.get(0), constructorSignature));
    } else {
        msg.format("Could not find any factories or constructors in %s matching node intrinsic", nodeClass);
        if (!nonMatches.isEmpty()) {
            msg.format("%nFactories and constructors that failed to match:");
            for (Map.Entry<ExecutableElement, String> e : nonMatches.entrySet()) {
                msg.format("%n  %s: %s", e.getKey(), e.getValue());
            }
        }
        env.getMessager().printMessage(Kind.ERROR, msg.toString(), intrinsicMethod, annotation);
    }
}
Also used : InjectedNodeParameter(org.graalvm.compiler.graph.Node.InjectedNodeParameter) HashMap(java.util.HashMap) TypeElement(javax.lang.model.element.TypeElement) Formatter(java.util.Formatter) ExecutableElement(javax.lang.model.element.ExecutableElement) VariableElement(javax.lang.model.element.VariableElement) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) Element(javax.lang.model.element.Element) VariableElement(javax.lang.model.element.VariableElement) TypeMirror(javax.lang.model.type.TypeMirror) TypeVariable(javax.lang.model.type.TypeVariable) NodeIntrinsic(org.graalvm.compiler.graph.Node.NodeIntrinsic)

Aggregations

Formatter (java.util.Formatter)1 HashMap (java.util.HashMap)1 Element (javax.lang.model.element.Element)1 ExecutableElement (javax.lang.model.element.ExecutableElement)1 TypeElement (javax.lang.model.element.TypeElement)1 VariableElement (javax.lang.model.element.VariableElement)1 TypeMirror (javax.lang.model.type.TypeMirror)1 TypeVariable (javax.lang.model.type.TypeVariable)1 InjectedNodeParameter (org.graalvm.compiler.graph.Node.InjectedNodeParameter)1 NodeIntrinsic (org.graalvm.compiler.graph.Node.NodeIntrinsic)1