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);
}
}
Aggregations