Search in sources :

Example 6 with NodeExecutionData

use of com.oracle.truffle.dsl.processor.model.NodeExecutionData in project graal by oracle.

the class NodeParser method parseExecutions.

private List<NodeExecutionData> parseExecutions(List<NodeFieldData> fields, List<NodeChildData> children, List<? extends Element> elements) {
    List<ExecutableElement> methods = ElementFilter.methodsIn(elements);
    boolean hasVarArgs = false;
    int maxSignatureSize = 0;
    if (!children.isEmpty()) {
        int lastIndex = children.size() - 1;
        hasVarArgs = children.get(lastIndex).getCardinality() == Cardinality.MANY;
        if (hasVarArgs) {
            maxSignatureSize = lastIndex;
        } else {
            maxSignatureSize = children.size();
        }
    }
    List<NodeFieldData> nonGetterFields = new ArrayList<>();
    for (NodeFieldData field : fields) {
        if (field.getGetter() == null && field.isGenerated()) {
            nonGetterFields.add(field);
        }
    }
    TypeMirror cacheAnnotation = context.getType(Cached.class);
    List<TypeMirror> frameTypes = context.getFrameTypes();
    // pre-parse specializations to find signature size
    for (ExecutableElement method : methods) {
        AnnotationMirror mirror = ElementUtils.findAnnotationMirror(processingEnv, method, Specialization.class);
        if (mirror == null) {
            continue;
        }
        int currentArgumentIndex = 0;
        parameter: for (VariableElement var : method.getParameters()) {
            TypeMirror type = var.asType();
            if (currentArgumentIndex == 0) {
                // skip optionals
                for (TypeMirror frameType : frameTypes) {
                    if (ElementUtils.typeEquals(type, frameType)) {
                        continue parameter;
                    }
                }
            }
            if (currentArgumentIndex < nonGetterFields.size()) {
                for (NodeFieldData field : nonGetterFields) {
                    if (ElementUtils.typeEquals(var.asType(), field.getType())) {
                        continue parameter;
                    }
                }
            }
            if (ElementUtils.findAnnotationMirror(var.getAnnotationMirrors(), cacheAnnotation) != null) {
                continue parameter;
            }
            currentArgumentIndex++;
        }
        maxSignatureSize = Math.max(maxSignatureSize, currentArgumentIndex);
    }
    List<NodeExecutionData> executions = new ArrayList<>();
    for (int i = 0; i < maxSignatureSize; i++) {
        boolean varArgParameter = false;
        int childIndex = i;
        if (i >= children.size() - 1) {
            if (hasVarArgs) {
                varArgParameter = hasVarArgs;
                childIndex = Math.min(i, children.size() - 1);
            } else if (i >= children.size()) {
                childIndex = -1;
            }
        }
        int varArgsIndex = -1;
        NodeChildData child = null;
        if (childIndex != -1) {
            varArgsIndex = varArgParameter ? Math.abs(childIndex - i) : -1;
            child = children.get(childIndex);
        }
        executions.add(new NodeExecutionData(child, i, varArgsIndex));
    }
    return executions;
}
Also used : NodeExecutionData(com.oracle.truffle.dsl.processor.model.NodeExecutionData) NodeChildData(com.oracle.truffle.dsl.processor.model.NodeChildData) CodeExecutableElement(com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) ArrayList(java.util.ArrayList) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) VariableElement(javax.lang.model.element.VariableElement) AnnotationMirror(javax.lang.model.element.AnnotationMirror) NodeFieldData(com.oracle.truffle.dsl.processor.model.NodeFieldData) ArrayCodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror)

Example 7 with NodeExecutionData

use of com.oracle.truffle.dsl.processor.model.NodeExecutionData in project graal by oracle.

the class NodeParser method initializeChildren.

@SuppressWarnings("unchecked")
private void initializeChildren(NodeData node) {
    for (NodeChildData child : node.getChildren()) {
        AnnotationValue executeWithValue1 = child.getExecuteWithValue();
        List<AnnotationValue> executeWithValues = ElementUtils.resolveAnnotationValue(List.class, executeWithValue1);
        List<NodeExecutionData> executeWith = new ArrayList<>();
        for (AnnotationValue executeWithValue : executeWithValues) {
            String executeWithString = ElementUtils.resolveAnnotationValue(String.class, executeWithValue);
            if (child.getName().equals(executeWithString)) {
                child.addError(executeWithValue1, "The child node '%s' cannot be executed with itself.", executeWithString);
                continue;
            }
            NodeExecutionData found = null;
            boolean before = true;
            for (NodeExecutionData resolveChild : node.getChildExecutions()) {
                if (resolveChild.getChild() == child) {
                    before = false;
                    continue;
                }
                if (resolveChild.getIndexedName().equals(executeWithString)) {
                    found = resolveChild;
                    break;
                }
            }
            if (found == null) {
                child.addError(executeWithValue1, "The child node '%s' cannot be executed with '%s'. The child node was not found.", child.getName(), executeWithString);
                continue;
            } else if (!before) {
                child.addError(executeWithValue1, "The child node '%s' cannot be executed with '%s'. The node %s is executed after the current node.", child.getName(), executeWithString, executeWithString);
                continue;
            }
            executeWith.add(found);
        }
        child.setExecuteWith(executeWith);
    }
    for (NodeChildData child : node.getChildren()) {
        TypeMirror nodeType = child.getNodeType();
        NodeData fieldNodeData = parseChildNodeData(node, child, ElementUtils.fromTypeMirror(nodeType));
        child.setNode(fieldNodeData);
        if (fieldNodeData == null || fieldNodeData.hasErrors()) {
            child.addError("Node type '%s' is invalid or not a subclass of Node.", ElementUtils.getQualifiedName(nodeType));
        } else {
            List<ExecutableTypeData> types = child.findGenericExecutableTypes(context);
            if (types.isEmpty()) {
                AnnotationValue executeWithValue = child.getExecuteWithValue();
                child.addError(executeWithValue, "No generic execute method found with %s evaluated arguments for node type %s and frame types %s.", child.getExecuteWith().size(), ElementUtils.getSimpleName(nodeType), ElementUtils.getUniqueIdentifiers(createAllowedChildFrameTypes(node)));
            }
        }
    }
}
Also used : ExecutableTypeData(com.oracle.truffle.dsl.processor.model.ExecutableTypeData) NodeChildData(com.oracle.truffle.dsl.processor.model.NodeChildData) NodeExecutionData(com.oracle.truffle.dsl.processor.model.NodeExecutionData) ArrayCodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror) ArrayList(java.util.ArrayList) AnnotationValue(javax.lang.model.element.AnnotationValue) NodeData(com.oracle.truffle.dsl.processor.model.NodeData)

Example 8 with NodeExecutionData

use of com.oracle.truffle.dsl.processor.model.NodeExecutionData in project graal by oracle.

the class NodeParser method initializePolymorphism.

private void initializePolymorphism(NodeData node) {
    if (!node.needsRewrites(context)) {
        return;
    }
    SpecializationData generic = node.getGenericSpecialization();
    List<VariableElement> types = new ArrayList<>();
    Collection<TypeMirror> frameTypes = new HashSet<>();
    for (SpecializationData specialization : node.getSpecializations()) {
        if (specialization.getFrame() != null) {
            frameTypes.add(specialization.getFrame().getType());
        }
    }
    if (node.supportsFrame()) {
        frameTypes.add(node.getFrameType());
    }
    if (!frameTypes.isEmpty()) {
        frameTypes = ElementUtils.uniqueSortedTypes(frameTypes, false);
        TypeMirror frameType;
        if (frameTypes.size() == 1) {
            frameType = frameTypes.iterator().next();
        } else {
            frameType = context.getType(Frame.class);
        }
        types.add(new CodeVariableElement(frameType, TemplateMethod.FRAME_NAME));
    }
    TypeMirror returnType = null;
    int index = 0;
    for (Parameter genericParameter : generic.getReturnTypeAndParameters()) {
        TypeMirror polymorphicType;
        if (genericParameter.getLocalName().equals(TemplateMethod.FRAME_NAME)) {
            continue;
        }
        boolean isReturnParameter = genericParameter == generic.getReturnType();
        if (!genericParameter.getSpecification().isSignature()) {
            polymorphicType = genericParameter.getType();
        } else {
            NodeExecutionData execution = genericParameter.getSpecification().getExecution();
            Collection<TypeMirror> usedTypes = new HashSet<>();
            for (SpecializationData specialization : node.getSpecializations()) {
                if (specialization.isUninitialized()) {
                    continue;
                }
                Parameter parameter = specialization.findParameter(genericParameter.getLocalName());
                if (parameter == specialization.getReturnType() && specialization.isFallback() && specialization.getMethod() == null) {
                    continue;
                }
                if (parameter == null) {
                    throw new AssertionError("Parameter existed in generic specialization but not in specialized. param = " + genericParameter.getLocalName());
                }
                if (isReturnParameter && specialization.hasUnexpectedResultRewrite()) {
                    if (!ElementUtils.isSubtypeBoxed(context, context.getType(Object.class), node.getGenericType(execution))) {
                        specialization.addError("Implicit 'Object' return type from UnexpectedResultException not compatible with generic type '%s'.", node.getGenericType(execution));
                    } else {
                        // if any specialization throws UnexpectedResultException, Object could
                        // be returned
                        usedTypes.add(context.getType(Object.class));
                    }
                }
                usedTypes.add(parameter.getType());
            }
            usedTypes = ElementUtils.uniqueSortedTypes(usedTypes, false);
            if (usedTypes.size() == 1) {
                polymorphicType = usedTypes.iterator().next();
            } else {
                polymorphicType = ElementUtils.getCommonSuperType(context, usedTypes);
            }
            if (execution != null && !ElementUtils.isSubtypeBoxed(context, polymorphicType, node.getGenericType(execution))) {
                throw new AssertionError(String.format("Polymorphic types %s not compatible to generic type %s.", polymorphicType, node.getGenericType(execution)));
            }
        }
        if (isReturnParameter) {
            returnType = polymorphicType;
        } else {
            types.add(new CodeVariableElement(polymorphicType, "param" + index));
        }
        index++;
    }
    SpecializationMethodParser parser = new SpecializationMethodParser(context, node);
    SpecializationData polymorphic = parser.create("Polymorphic", TemplateMethod.NO_NATURAL_ORDER, null, null, returnType, types);
    if (polymorphic == null) {
        throw new AssertionError("Failed to parse polymorphic signature. " + parser.createDefaultMethodSpec(null, null, false, null) + " Types: " + returnType + " - " + types);
    }
    polymorphic.setKind(SpecializationKind.POLYMORPHIC);
    node.getSpecializations().add(polymorphic);
}
Also used : Frame(com.oracle.truffle.api.frame.Frame) NodeExecutionData(com.oracle.truffle.dsl.processor.model.NodeExecutionData) SpecializationData(com.oracle.truffle.dsl.processor.model.SpecializationData) ArrayList(java.util.ArrayList) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) VariableElement(javax.lang.model.element.VariableElement) ArrayCodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) Parameter(com.oracle.truffle.dsl.processor.model.Parameter) HashSet(java.util.HashSet)

Example 9 with NodeExecutionData

use of com.oracle.truffle.dsl.processor.model.NodeExecutionData in project graal by oracle.

the class NodeParser method createGenericType.

private TypeMirror createGenericType(NodeData node, ParameterSpec spec) {
    NodeExecutionData execution = spec.getExecution();
    Collection<TypeMirror> allowedTypes;
    if (execution == null) {
        allowedTypes = spec.getAllowedTypes();
    } else {
        allowedTypes = Arrays.asList(node.getGenericType(execution));
    }
    if (allowedTypes.size() == 1) {
        return allowedTypes.iterator().next();
    } else {
        return ElementUtils.getCommonSuperType(context, allowedTypes);
    }
}
Also used : NodeExecutionData(com.oracle.truffle.dsl.processor.model.NodeExecutionData) ArrayCodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror)

Example 10 with NodeExecutionData

use of com.oracle.truffle.dsl.processor.model.NodeExecutionData in project graal by oracle.

the class NodeParser method initializeExecutableTypes.

private void initializeExecutableTypes(NodeData node) {
    List<ExecutableTypeData> allExecutes = node.getExecutableTypes();
    Set<String> inconsistentFrameTypes = new HashSet<>();
    TypeMirror frameType = null;
    for (ExecutableTypeData execute : allExecutes) {
        TypeMirror frame = execute.getFrameParameter();
        TypeMirror resolvedFrameType;
        if (frame != null) {
            resolvedFrameType = frame;
            if (frameType == null) {
                frameType = resolvedFrameType;
            } else if (!ElementUtils.typeEquals(frameType, resolvedFrameType)) {
                // found inconsistent frame types
                inconsistentFrameTypes.add(ElementUtils.getSimpleName(frameType));
                inconsistentFrameTypes.add(ElementUtils.getSimpleName(resolvedFrameType));
            }
        }
    }
    if (!inconsistentFrameTypes.isEmpty()) {
        // ensure they are sorted somehow
        List<String> inconsistentFrameTypesList = new ArrayList<>(inconsistentFrameTypes);
        Collections.sort(inconsistentFrameTypesList);
        node.addError("Invalid inconsistent frame types %s found for the declared execute methods. The frame type must be identical for all execute methods.", inconsistentFrameTypesList);
    }
    if (frameType == null) {
        frameType = context.getType(void.class);
    }
    node.setFrameType(frameType);
    boolean genericFound = false;
    for (ExecutableTypeData type : node.getExecutableTypes()) {
        if (!type.hasUnexpectedValue(context)) {
            genericFound = true;
            break;
        }
    }
    // no generic executes
    if (!genericFound) {
        node.addError("No accessible and overridable generic execute method found. Generic execute methods usually have the " + "signature 'public abstract {Type} execute(VirtualFrame)' and must not throw any checked exceptions.");
    }
    int nodeChildDeclarations = 0;
    int nodeChildDeclarationsRequired = 0;
    List<NodeExecutionData> executions = node.getChildExecutions();
    for (NodeExecutionData execution : executions) {
        if (execution.getChild() == null) {
            nodeChildDeclarationsRequired = execution.getIndex() + 1;
        } else {
            nodeChildDeclarations++;
        }
    }
    List<String> requireNodeChildDeclarations = new ArrayList<>();
    for (ExecutableTypeData type : allExecutes) {
        if (type.getEvaluatedCount() < nodeChildDeclarationsRequired) {
            requireNodeChildDeclarations.add(ElementUtils.createReferenceName(type.getMethod()));
        }
    }
    if (!requireNodeChildDeclarations.isEmpty()) {
        node.addError("Not enough child node declarations found. Please annotate the node class with addtional @NodeChild annotations or remove all execute methods that do not provide all evaluated values. " + "The following execute methods do not provide all evaluated values for the expected signature size %s: %s.", executions.size(), requireNodeChildDeclarations);
    }
    if (nodeChildDeclarations > 0 && executions.size() == node.getMinimalEvaluatedParameters()) {
        for (NodeChildData child : node.getChildren()) {
            child.addError("Unnecessary @NodeChild declaration. All evaluated child values are provided as parameters in execute methods.");
        }
    }
}
Also used : ExecutableTypeData(com.oracle.truffle.dsl.processor.model.ExecutableTypeData) NodeExecutionData(com.oracle.truffle.dsl.processor.model.NodeExecutionData) NodeChildData(com.oracle.truffle.dsl.processor.model.NodeChildData) ArrayList(java.util.ArrayList) ArrayCodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror) HashSet(java.util.HashSet)

Aggregations

NodeExecutionData (com.oracle.truffle.dsl.processor.model.NodeExecutionData)18 ArrayList (java.util.ArrayList)11 ArrayCodeTypeMirror (com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror)10 TypeMirror (javax.lang.model.type.TypeMirror)10 CodeTreeBuilder (com.oracle.truffle.dsl.processor.java.model.CodeTreeBuilder)8 NodeChildData (com.oracle.truffle.dsl.processor.model.NodeChildData)6 CodeExecutableElement (com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement)5 CodeTree (com.oracle.truffle.dsl.processor.java.model.CodeTree)5 CodeVariableElement (com.oracle.truffle.dsl.processor.java.model.CodeVariableElement)5 DeclaredCodeTypeMirror (com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror)4 GeneratedTypeMirror (com.oracle.truffle.dsl.processor.java.model.GeneratedTypeMirror)4 ExecutableTypeData (com.oracle.truffle.dsl.processor.model.ExecutableTypeData)4 Parameter (com.oracle.truffle.dsl.processor.model.Parameter)4 SpecializationData (com.oracle.truffle.dsl.processor.model.SpecializationData)4 ExecutableElement (javax.lang.model.element.ExecutableElement)3 VariableElement (javax.lang.model.element.VariableElement)3 NodeFieldData (com.oracle.truffle.dsl.processor.model.NodeFieldData)2 TypeGuard (com.oracle.truffle.dsl.processor.parser.SpecializationGroup.TypeGuard)2 HashSet (java.util.HashSet)2 UnsupportedSpecializationException (com.oracle.truffle.api.dsl.UnsupportedSpecializationException)1