Search in sources :

Example 1 with ElementUtils.findAnnotationMirror

use of com.oracle.truffle.dsl.processor.java.ElementUtils.findAnnotationMirror in project graal by oracle.

the class NodeParser method parseChildren.

private List<NodeChildData> parseChildren(NodeData node, final List<TypeElement> typeHierarchy, List<? extends Element> elements) {
    Map<String, TypeMirror> castNodeTypes = new HashMap<>();
    for (ExecutableElement method : ElementFilter.methodsIn(elements)) {
        AnnotationMirror mirror = findAnnotationMirror(method, types.CreateCast);
        if (mirror != null) {
            List<String> children = (getAnnotationValueList(String.class, mirror, "value"));
            if (children != null) {
                for (String child : children) {
                    castNodeTypes.put(child, method.getReturnType());
                }
            }
        }
    }
    List<NodeChildData> executedFieldChildren = new ArrayList<>();
    for (VariableElement field : ElementFilter.fieldsIn(elements)) {
        if (field.getModifiers().contains(Modifier.STATIC)) {
            continue;
        }
        AnnotationMirror executed = findAnnotationMirror(field.getAnnotationMirrors(), types.Executed);
        if (executed != null) {
            TypeMirror type = field.asType();
            String name = field.getSimpleName().toString();
            Cardinality cardinality = Cardinality.ONE;
            if (type.getKind() == TypeKind.ARRAY) {
                cardinality = Cardinality.MANY;
            }
            AnnotationValue executedWith = getAnnotationValue(executed, "with");
            NodeChildData child = new NodeChildData(field, executed, name, type, type, field, cardinality, executedWith, null, null);
            executedFieldChildren.add(child);
            if (field.getModifiers().contains(Modifier.PRIVATE)) {
                child.addError("Field annotated with @%s must be visible for the generated subclass to execute.", types.Executed.asElement().getSimpleName().toString());
            }
            if (cardinality == Cardinality.ONE) {
                if (ElementUtils.findAnnotationMirror(field, types.Node_Child) == null) {
                    child.addError("Field annotated with @%s must also be annotated with @%s.", types.Executed.asElement().getSimpleName().toString(), types.Node_Child.asElement().getSimpleName().toString());
                }
            } else {
                assert cardinality == Cardinality.MANY;
                if (ElementUtils.findAnnotationMirror(field, types.Node_Children) == null) {
                    child.addError("Field annotated with @%s must also be annotated with @%s.", types.Executed.asElement().getSimpleName().toString(), types.Node_Children.asElement().getSimpleName().toString());
                }
            }
        }
    }
    NodeChildData many = null;
    Set<String> names = new HashSet<>();
    for (NodeChildData child : executedFieldChildren) {
        if (child.needsGeneratedField()) {
            throw new AssertionError("Should not need generated field.");
        }
        if (names.contains(child.getName())) {
            child.addError("Field annotated with @%s has duplicate name '%s'. " + "Executed children must have unique names.", types.Executed.asElement().getSimpleName().toString(), child.getName());
        } else if (many != null) {
            child.addError("Field annotated with @%s is hidden by executed field '%s'. " + "Executed child fields with multiple children hide all following executed child declarations. " + "Reorder or remove this executed child declaration.", types.Executed.asElement().getSimpleName().toString(), many.getName());
        } else if (child.getCardinality().isMany()) {
            many = child;
        }
        names.add(child.getName());
    }
    List<NodeChildData> nodeChildren = new ArrayList<>();
    List<TypeElement> typeHierarchyReversed = new ArrayList<>(typeHierarchy);
    Collections.reverse(typeHierarchyReversed);
    for (TypeElement type : typeHierarchyReversed) {
        AnnotationMirror nodeChildrenMirror = findAnnotationMirror(type, types.NodeChildren);
        TypeMirror nodeClassType = type.getSuperclass();
        if (nodeClassType.getKind() == TypeKind.NONE || !isAssignable(nodeClassType, types.Node)) {
            nodeClassType = null;
        }
        List<AnnotationMirror> children = collectAnnotations(nodeChildrenMirror, "value", type, types.NodeChild);
        int index = 0;
        for (AnnotationMirror childMirror : children) {
            String name = getAnnotationValue(String.class, childMirror, "value");
            if (name.equals("")) {
                name = "child" + index;
            }
            Cardinality cardinality = Cardinality.ONE;
            TypeMirror childNodeType = inheritType(childMirror, "type", nodeClassType);
            if (childNodeType.getKind() == TypeKind.ARRAY) {
                cardinality = Cardinality.MANY;
            }
            TypeMirror originalChildType = childNodeType;
            TypeMirror castNodeType = castNodeTypes.get(name);
            if (castNodeType != null) {
                childNodeType = castNodeType;
            }
            Element getter = findGetter(elements, name, childNodeType);
            AnnotationValue executeWith = getAnnotationValue(childMirror, "executeWith");
            String create = null;
            boolean implicit = (boolean) unboxAnnotationValue(getAnnotationValue(childMirror, "implicit"));
            boolean implicitCreateSpecified = getAnnotationValue(childMirror, "implicitCreate", false) != null;
            if (implicit || implicitCreateSpecified) {
                create = (String) unboxAnnotationValue(getAnnotationValue(childMirror, "implicitCreate"));
            }
            String uncached = null;
            boolean allowUncached = (boolean) unboxAnnotationValue(getAnnotationValue(childMirror, "allowUncached"));
            boolean uncachedSpecified = getAnnotationValue(childMirror, "uncached", false) != null;
            if (allowUncached || uncachedSpecified) {
                uncached = (String) unboxAnnotationValue(getAnnotationValue(childMirror, "uncached"));
            }
            NodeChildData nodeChild = new NodeChildData(type, childMirror, name, childNodeType, originalChildType, getter, cardinality, executeWith, create, uncached);
            if (implicitCreateSpecified && implicit) {
                nodeChild.addError("The attributes 'implicit' and 'implicitCreate' are mutually exclusive. Remove one of the attributes to resolve this.");
            }
            if (uncachedSpecified && allowUncached) {
                nodeChild.addError("The attributes 'allowUncached' and 'uncached' are mutually exclusive. Remove one of the attributes to resolve this.");
            }
            nodeChildren.add(nodeChild);
            if (nodeChild.getNodeType() == null) {
                nodeChild.addError("No valid node type could be resolved.");
            }
            if (nodeChild.hasErrors()) {
                continue;
            }
            index++;
        }
    }
    if (!nodeChildren.isEmpty() && !executedFieldChildren.isEmpty()) {
        node.addError("The use of @%s and @%s at the same time is not supported.", types.NodeChild.asElement().getSimpleName().toString(), types.Executed.asElement().getSimpleName().toString());
        return executedFieldChildren;
    } else if (!executedFieldChildren.isEmpty()) {
        return executedFieldChildren;
    } else {
        List<NodeChildData> filteredChildren = new ArrayList<>();
        Set<String> encounteredNames = new HashSet<>();
        for (int i = nodeChildren.size() - 1; i >= 0; i--) {
            NodeChildData child = nodeChildren.get(i);
            if (!encounteredNames.contains(child.getName())) {
                filteredChildren.add(0, child);
                encounteredNames.add(child.getName());
            }
        }
        return filteredChildren;
    }
}
Also used : Set(java.util.Set) LinkedHashSet(java.util.LinkedHashSet) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) HashMap(java.util.HashMap) CodeExecutableElement(com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) TypeElement(javax.lang.model.element.TypeElement) GeneratedElement(com.oracle.truffle.dsl.processor.java.model.GeneratedElement) CodeExecutableElement(com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement) Element(javax.lang.model.element.Element) VariableElement(javax.lang.model.element.VariableElement) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) CodeTypeElement(com.oracle.truffle.dsl.processor.java.model.CodeTypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) ArrayList(java.util.ArrayList) VariableElement(javax.lang.model.element.VariableElement) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) ElementUtils.fromTypeMirror(com.oracle.truffle.dsl.processor.java.ElementUtils.fromTypeMirror) CodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror) ArrayCodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror) ArrayList(java.util.ArrayList) ElementUtils.getAnnotationValueList(com.oracle.truffle.dsl.processor.java.ElementUtils.getAnnotationValueList) List(java.util.List) LinkedHashSet(java.util.LinkedHashSet) HashSet(java.util.HashSet) NodeChildData(com.oracle.truffle.dsl.processor.model.NodeChildData) Cardinality(com.oracle.truffle.dsl.processor.model.NodeChildData.Cardinality) TypeElement(javax.lang.model.element.TypeElement) CodeTypeElement(com.oracle.truffle.dsl.processor.java.model.CodeTypeElement) ElementUtils.findAnnotationMirror(com.oracle.truffle.dsl.processor.java.ElementUtils.findAnnotationMirror) AnnotationMirror(javax.lang.model.element.AnnotationMirror) AnnotationValue(javax.lang.model.element.AnnotationValue) ElementUtils.getAnnotationValue(com.oracle.truffle.dsl.processor.java.ElementUtils.getAnnotationValue) ElementUtils.unboxAnnotationValue(com.oracle.truffle.dsl.processor.java.ElementUtils.unboxAnnotationValue) ElementUtils.resolveAnnotationValue(com.oracle.truffle.dsl.processor.java.ElementUtils.resolveAnnotationValue)

Example 2 with ElementUtils.findAnnotationMirror

use of com.oracle.truffle.dsl.processor.java.ElementUtils.findAnnotationMirror in project graal by oracle.

the class NodeParser method initializeAOT.

private void initializeAOT(NodeData node) {
    if (!node.isGenerateAOT()) {
        return;
    }
    // apply exclude rules
    for (SpecializationData specialization : node.getSpecializations()) {
        if (!specialization.isReachable() || specialization.getMethod() == null) {
            continue;
        }
        AnnotationMirror mirror = ElementUtils.findAnnotationMirror(specialization.getMethod(), types.GenerateAOT_Exclude);
        if (mirror != null) {
            // explicitly excluded
            continue;
        }
        specialization.setPrepareForAOT(true);
    }
    // exclude uncached specializations
    for (SpecializationData specialization : node.getSpecializations()) {
        if (specialization.getUncachedSpecialization() != null) {
            specialization.getUncachedSpecialization().setPrepareForAOT(false);
        }
    }
    // second pass to remove replaced specializations
    outer: for (SpecializationData specialization : node.getSpecializations()) {
        if (!specialization.isPrepareForAOT()) {
            continue;
        }
        // not reachable during AOT
        for (SpecializationData otherSpecialization : node.getSpecializations()) {
            if (otherSpecialization.getReplaces().contains(specialization) && otherSpecialization.isPrepareForAOT()) {
                specialization.setPrepareForAOT(false);
                continue outer;
            }
        }
    }
    // third pass validate included specializations
    outer: for (SpecializationData specialization : node.getSpecializations()) {
        if (!specialization.isPrepareForAOT()) {
            continue;
        }
        for (CacheExpression cache : specialization.getCaches()) {
            if (ElementUtils.typeEquals(cache.getParameter().getType(), node.getTemplateType().asType())) {
                if (specialization.getGuards().isEmpty()) {
                    if (cache.usesDefaultCachedInitializer()) {
                        // guaranteed recursion
                        cache.addError(// 
                        "Failed to generate code for @%s: " + // 
                        "Recursive AOT preparation detected. Recursive AOT preparation is not supported as this would lead to infinite compiled code." + // 
                        "Resolve this problem by either: %n" + // 
                        " - Exclude this specialization from AOT with @%s.%s if it is acceptable to deoptimize for this specialization in AOT compiled code. %n" + // 
                        " - Configure the specialization to be replaced with a more generic specialization. %n" + // 
                        " - Add a specialization guard that guarantees that the recursion is finite. %n" + // 
                        " - Remove the cached parameter value. %n", getSimpleName(types.GenerateAOT), getSimpleName(types.GenerateAOT), getSimpleName(types.GenerateAOT_Exclude));
                        continue;
                    }
                }
            }
            if (cache.isMergedLibrary()) {
                cache.addError(// 
                "Merged libraries are not supported in combination with AOT preparation. " + // 
                "Resolve this problem by either: %n" + // 
                " - Setting @%s(..., useForAOT=false) to disable AOT preparation for this export. %n" + // 
                " - Using a dispatched library without receiver expression. %n" + " - Adding the @%s.%s annotation to the specialization or exported method.", getSimpleName(types.ExportLibrary), getSimpleName(types.GenerateAOT), getSimpleName(types.GenerateAOT_Exclude));
                continue;
            }
            TypeMirror type = cache.getParameter().getType();
            if (NodeCodeGenerator.isSpecializedNode(type)) {
                List<TypeElement> lookupTypes = collectSuperClasses(new ArrayList<TypeElement>(), ElementUtils.castTypeElement(type));
                AnnotationMirror generateAOT = findFirstAnnotation(lookupTypes, types.GenerateAOT);
                if (generateAOT == null) {
                    cache.addError(// 
                    "Failed to generate code for @%s: " + // 
                    "Referenced node type cannot be initialized for AOT." + // 
                    "Resolve this problem by either: %n" + // 
                    " - Exclude this specialization from AOT with @%s.%s if it is acceptable to deoptimize for this specialization in AOT compiled code. %n" + // 
                    " - Configure the specialization to be replaced with a more generic specialization. %n" + // 
                    " - Remove the cached parameter value. %n" + " - Add the @%s annotation to node type '%s' or one of its super types.", getSimpleName(types.GenerateAOT), getSimpleName(types.GenerateAOT), getSimpleName(types.GenerateAOT_Exclude), getSimpleName(types.GenerateAOT), getSimpleName(type));
                    continue;
                }
            }
            boolean cachedLibraryAOT = false;
            if (cache.isCachedLibrary()) {
                cachedLibraryAOT = ElementUtils.findAnnotationMirror(ElementUtils.fromTypeMirror(cache.getParameter().getType()), types.GenerateAOT) != null;
            }
            if (cache.isCachedLibrary() && cache.getCachedLibraryLimit() != null && !cache.getCachedLibraryLimit().equals("")) {
                if (!cachedLibraryAOT) {
                    cache.addError(// 
                    "Failed to generate code for @%s: " + // 
                    "@%s with automatic dispatch cannot be prepared for AOT." + // 
                    "Resolve this problem by either: %n" + // 
                    " - Exclude this specialization from AOT with @%s.%s if it is acceptable to deoptimize for this specialization in AOT compiled code. %n" + // 
                    " - Configure the specialization to be replaced with a more generic specialization. %n" + // 
                    " - Remove the cached parameter value. %n" + // 
                    " - Define a cached library initializer expression for manual dispatch. %n" + " - Add the @%s annotation to the %s library class to enable AOT for the library.", getSimpleName(types.GenerateAOT), getSimpleName(types.CachedLibrary), getSimpleName(types.GenerateAOT), getSimpleName(types.GenerateAOT_Exclude), getSimpleName(types.GenerateAOT), getSimpleName(type));
                    continue;
                }
            }
            if (!cache.isCachedContext() && !cache.isCachedLanguage() && specialization.isDynamicParameterBound(cache.getDefaultExpression(), true)) {
                /*
                     * We explicitly support cached language references and lookups thereof in AOT.
                     * But the generated code introduces a check to ensure that only the language of
                     * the root node is used.
                     */
                if (specialization.isOnlyLanguageReferencesBound(cache.getDefaultExpression())) {
                    continue;
                }
                if (!cachedLibraryAOT) {
                    cache.addError(// 
                    "Failed to generate code for @%s: " + // 
                    "Cached values in specializations included for AOT must not bind dynamic values. " + // 
                    "Such caches are only allowed to bind static values, values read from the node or values from the current language instance using a language reference. " + // 
                    "Resolve this problem by either: %n" + // 
                    " - Exclude this specialization from AOT with @%s.%s if it is acceptable to deoptimize for this specialization in AOT compiled code. %n" + // 
                    " - Configure the specialization to be replaced with a more generic specialization. %n" + // 
                    " - Remove the cached parameter value. %n" + // 
                    " - Avoid binding dynamic parameters in the cache initializer expression. %n" + " - If a cached library is used add the @%s annotation to the library class to enable AOT for the library.", getSimpleName(types.GenerateAOT), getSimpleName(types.GenerateAOT), getSimpleName(types.GenerateAOT_Exclude), getSimpleName(types.GenerateAOT));
                    continue outer;
                }
            }
        }
    }
}
Also used : ElementUtils.findAnnotationMirror(com.oracle.truffle.dsl.processor.java.ElementUtils.findAnnotationMirror) AnnotationMirror(javax.lang.model.element.AnnotationMirror) ElementUtils.fromTypeMirror(com.oracle.truffle.dsl.processor.java.ElementUtils.fromTypeMirror) CodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror) ArrayCodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror) SpecializationData(com.oracle.truffle.dsl.processor.model.SpecializationData) ArrayList(java.util.ArrayList) ArrayList(java.util.ArrayList) ElementUtils.getAnnotationValueList(com.oracle.truffle.dsl.processor.java.ElementUtils.getAnnotationValueList) List(java.util.List) CacheExpression(com.oracle.truffle.dsl.processor.model.CacheExpression)

Example 3 with ElementUtils.findAnnotationMirror

use of com.oracle.truffle.dsl.processor.java.ElementUtils.findAnnotationMirror in project graal by oracle.

the class NodeParser method initializeCaches.

private SpecializationData initializeCaches(SpecializationData specialization, DSLExpressionResolver resolver) {
    List<CacheExpression> caches = new ArrayList<>();
    List<CacheExpression> cachedLibraries = new ArrayList<>();
    Parameter[] parameters = specialization.getParameters().toArray(new Parameter[0]);
    parameters: for (Parameter parameter : parameters) {
        if (!parameter.getSpecification().isCached()) {
            continue;
        }
        AnnotationMirror foundCached = null;
        for (TypeMirror cachedAnnotation : cachedAnnotations) {
            AnnotationMirror found = ElementUtils.findAnnotationMirror(parameter.getVariableElement().getAnnotationMirrors(), cachedAnnotation);
            if (found == null) {
                continue;
            }
            if (foundCached == null) {
                foundCached = found;
            } else {
                StringBuilder b = new StringBuilder();
                String sep = "";
                for (TypeMirror stringCachedAnnotation : cachedAnnotations) {
                    b.append(sep);
                    b.append("@");
                    b.append(ElementUtils.getSimpleName(stringCachedAnnotation));
                    sep = ", ";
                }
                specialization.addError(parameter.getVariableElement(), "The following annotations are mutually exclusive for a parameter: %s.", b.toString());
                continue parameters;
            }
        }
        if (foundCached == null) {
            continue;
        }
        CacheExpression cache = new CacheExpression(parameter, foundCached);
        caches.add(cache);
        if (cache.isCached()) {
            boolean weakReference = getAnnotationValue(Boolean.class, foundCached, "weak");
            if (weakReference) {
                if (ElementUtils.isPrimitive(cache.getParameter().getType())) {
                    cache.addError("Cached parameters with primitive types cannot be weak. Set weak to false to resolve this.");
                }
                parseCached(cache, specialization, resolver, parameter);
                if (cache.hasErrors()) {
                    continue;
                }
                DSLExpression sourceExpression = cache.getDefaultExpression();
                String weakName = "weak" + ElementUtils.firstLetterUpperCase(parameter.getLocalName()) + "Gen_";
                TypeMirror weakType = new CodeTypeMirror.DeclaredCodeTypeMirror(context.getTypeElement(types.TruffleWeakReference), Arrays.asList(cache.getParameter().getType()));
                CodeVariableElement weakVariable = new CodeVariableElement(weakType, weakName);
                weakVariable.setEnclosingElement(specialization.getMethod());
                Parameter weakParameter = new Parameter(parameter, weakVariable);
                DSLExpression newWeakReference = new DSLExpression.Call(null, "new", Arrays.asList(sourceExpression));
                newWeakReference.setResolvedTargetType(weakType);
                resolveCachedExpression(resolver, cache, weakType, newWeakReference, null);
                CacheExpression weakCache = new CacheExpression(weakParameter, foundCached);
                weakCache.setDefaultExpression(newWeakReference);
                weakCache.setUncachedExpression(newWeakReference);
                weakCache.setWeakReference(true);
                caches.add(0, weakCache);
                DSLExpressionResolver weakResolver = resolver.copy(Arrays.asList());
                weakResolver.addVariable(weakName, weakVariable);
                specialization.addParameter(specialization.getParameters().size(), weakParameter);
                DSLExpression parsedDefaultExpression = parseCachedExpression(weakResolver, cache, parameter.getType(), weakName + ".get()");
                cache.setDefaultExpression(parsedDefaultExpression);
                cache.setUncachedExpression(sourceExpression);
                cache.setAlwaysInitialized(true);
                cache.setWeakReferenceGet(true);
            } else {
                parseCached(cache, specialization, resolver, parameter);
            }
        } else if (cache.isCachedLibrary()) {
            String expression = cache.getCachedLibraryExpression();
            String limit = cache.getCachedLibraryLimit();
            if (expression == null) {
                // its cached dispatch version treat it as normal cached
                if (limit == null) {
                    cache.addError("A specialized value expression or limit must be specified for @%s. " + "Use @%s(\"value\") for a specialized or " + "@%s(limit=\"\") for a dispatched library. " + "See the javadoc of @%s for further details.", types.CachedLibrary.asElement().getSimpleName().toString(), types.CachedLibrary.asElement().getSimpleName().toString(), types.CachedLibrary.asElement().getSimpleName().toString(), types.CachedLibrary.asElement().getSimpleName().toString());
                    continue;
                }
                DSLExpression limitExpression = parseCachedExpression(resolver, cache, context.getType(int.class), limit);
                if (limitExpression == null) {
                    continue;
                }
                TypeMirror libraryType = types.Library;
                DSLExpressionResolver cachedResolver = importStatics(resolver, types.LibraryFactory);
                TypeMirror usedLibraryType = parameter.getType();
                DSLExpression resolveCall = new DSLExpression.Call(null, "resolve", Arrays.asList(new DSLExpression.ClassLiteral(usedLibraryType)));
                DSLExpression defaultExpression = new DSLExpression.Call(resolveCall, "createDispatched", Arrays.asList(limitExpression));
                DSLExpression uncachedExpression = new DSLExpression.Call(resolveCall, "getUncached", Arrays.asList());
                cache.setDefaultExpression(resolveCachedExpression(cachedResolver, cache, libraryType, defaultExpression, null));
                cache.setUncachedExpression(resolveCachedExpression(cachedResolver, cache, libraryType, uncachedExpression, null));
            } else {
                if (limit != null) {
                    cache.addError("The limit and specialized value expression cannot be specified at the same time. They are mutually exclusive.");
                    continue parameters;
                }
                cachedLibraries.add(cache);
            }
        } else if (cache.isCachedLanguage()) {
            TypeMirror languageType = cache.getParameter().getType();
            boolean isLanguage = ElementUtils.isAssignable(languageType, types.TruffleLanguage);
            boolean isLanguageReference = ElementUtils.isAssignable(languageType, types.TruffleLanguage_LanguageReference);
            if (!isLanguage && !isLanguageReference) {
                cache.addError("Invalid @%s specification. The parameter type must be a subtype of %s or of type LanguageReference<%s>.", types.CachedLanguage.asElement().getSimpleName().toString(), types.TruffleLanguage.asElement().getSimpleName().toString(), types.TruffleLanguage.asElement().getSimpleName().toString());
                continue parameters;
            }
            TypeMirror referenceType;
            if (isLanguageReference) {
                TypeMirror typeArgument = getFirstTypeArgument(languageType);
                if (typeArgument == null || !ElementUtils.isAssignable(typeArgument, types.TruffleLanguage)) {
                    cache.addError("Invalid @%s specification. The first type argument of the LanguageReference must be a subtype of '%s'.", types.CachedLanguage.asElement().getSimpleName().toString(), types.TruffleLanguage.asElement().getSimpleName().toString());
                } else {
                    verifyLanguageType(types.CachedLanguage, cache, typeArgument);
                }
                referenceType = languageType;
                languageType = typeArgument;
            } else {
                verifyLanguageType(types.CachedLanguage, cache, languageType);
                referenceType = new CodeTypeMirror.DeclaredCodeTypeMirror(context.getTypeElement(types.TruffleLanguage_LanguageReference), Arrays.asList(languageType));
            }
            if (cache.hasErrors()) {
                continue parameters;
            }
            DSLExpressionResolver cachedResolver = importStatics(resolver, types.TruffleLanguage_LanguageReference);
            DSLExpression.Variable thisReceiver = new DSLExpression.Variable(null, "this");
            cachedResolver.addVariable("this", new CodeVariableElement(types.Node, "this"));
            DSLExpression expression = new DSLExpression.Call(null, "create", Arrays.asList(new DSLExpression.ClassLiteral(languageType)));
            if (isLanguage) {
                expression = new DSLExpression.Call(expression, "get", Collections.singletonList(thisReceiver));
            }
            cache.setReferenceType(referenceType);
            cache.setLanguageType(languageType);
            cache.setDefaultExpression(resolveCachedExpression(cachedResolver, cache, null, expression, null));
            cache.setUncachedExpression(resolveCachedExpression(cachedResolver, cache, null, expression, null));
            cache.setAlwaysInitialized(true);
        } else if (cache.isCachedContext()) {
            AnnotationMirror cachedContext = cache.getMessageAnnotation();
            TypeMirror languageType = ElementUtils.getAnnotationValue(TypeMirror.class, cachedContext, "value");
            if (!ElementUtils.isAssignable(languageType, languageType)) {
                cache.addError("Invalid @%s specification. The value type must be a subtype of %s.", types.CachedContext.asElement().getSimpleName().toString(), types.TruffleLanguage.asElement().getSimpleName().toString());
                continue parameters;
            }
            verifyLanguageType(types.CachedContext, cache, languageType);
            if (cache.hasErrors()) {
                continue parameters;
            }
            TypeMirror contextType = findContextTypeFromLanguage(languageType);
            if (contextType == null || contextType.getKind() != TypeKind.DECLARED) {
                cache.addError("Invalid @%s specification. The context type could not be inferred from super type in language '%s'.", types.CachedContext.asElement().getSimpleName().toString(), ElementUtils.getSimpleName(languageType));
                continue parameters;
            }
            TypeMirror declaredContextType = parameter.getType();
            if (ElementUtils.typeEquals(ElementUtils.eraseGenericTypes(parameter.getType()), ElementUtils.eraseGenericTypes(types.TruffleLanguage_ContextReference))) {
                declaredContextType = getFirstTypeArgument(parameter.getType());
            }
            if (!ElementUtils.typeEquals(contextType, declaredContextType)) {
                cache.addError("Invalid @%s specification. The parameter type must match the context type '%s' or 'ContextReference<%s>'.", types.CachedContext.asElement().getSimpleName().toString(), ElementUtils.getSimpleName(contextType), ElementUtils.getSimpleName(contextType));
                continue parameters;
            }
            TypeMirror referenceType = new CodeTypeMirror.DeclaredCodeTypeMirror(context.getTypeElement(types.TruffleLanguage_ContextReference), Arrays.asList(contextType));
            cache.setReferenceType(referenceType);
            cache.setLanguageType(languageType);
            DSLExpressionResolver cachedResolver = importStatics(resolver, types.TruffleLanguage_ContextReference);
            DSLExpression.Variable thisReceiver = new DSLExpression.Variable(null, "this");
            cachedResolver.addVariable("this", new CodeVariableElement(types.Node, "this"));
            DSLExpression expression = new DSLExpression.Call(null, "create", Arrays.asList(new DSLExpression.ClassLiteral(languageType)));
            if (!cache.isReference()) {
                expression = new DSLExpression.Call(expression, "get", Collections.singletonList(thisReceiver));
            }
            cache.setDefaultExpression(resolveCachedExpression(cachedResolver, cache, null, expression, null));
            cache.setUncachedExpression(resolveCachedExpression(cachedResolver, cache, null, expression, null));
            cache.setAlwaysInitialized(true);
        } else if (cache.isBind()) {
            AnnotationMirror dynamic = cache.getMessageAnnotation();
            String expression = ElementUtils.getAnnotationValue(String.class, dynamic, "value", false);
            DSLExpression parsedExpression = parseCachedExpression(resolver, cache, parameter.getType(), expression);
            cache.setDefaultExpression(parsedExpression);
            cache.setUncachedExpression(parsedExpression);
            cache.setAlwaysInitialized(true);
        }
    }
    specialization.setCaches(caches);
    SpecializationData uncachedSpecialization = null;
    if (!cachedLibraries.isEmpty()) {
        uncachedSpecialization = parseCachedLibraries(specialization, resolver, cachedLibraries);
    }
    if (specialization.hasErrors()) {
        return null;
    }
    // verify that cache expressions are bound in the correct order.
    for (int i = 0; i < caches.size(); i++) {
        CacheExpression currentExpression = caches.get(i);
        Set<VariableElement> boundVariables = new HashSet<>();
        if (currentExpression.getDefaultExpression() != null) {
            boundVariables.addAll(currentExpression.getDefaultExpression().findBoundVariableElements());
        }
        if (currentExpression.getUncachedExpression() != null) {
            boundVariables.addAll(currentExpression.getUncachedExpression().findBoundVariableElements());
        }
        for (int j = i + 1; j < caches.size(); j++) {
            CacheExpression boundExpression = caches.get(j);
            if (boundVariables.contains(boundExpression.getParameter().getVariableElement())) {
                currentExpression.addError("The initializer expression of parameter '%s' binds uninitialized parameter '%s. Reorder the parameters to resolve the problem.", currentExpression.getParameter().getLocalName(), boundExpression.getParameter().getLocalName());
                break;
            }
        }
    }
    return uncachedSpecialization;
}
Also used : Variable(com.oracle.truffle.dsl.processor.expression.DSLExpression.Variable) ArrayList(java.util.ArrayList) VariableElement(javax.lang.model.element.VariableElement) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) DSLExpression(com.oracle.truffle.dsl.processor.expression.DSLExpression) CacheExpression(com.oracle.truffle.dsl.processor.model.CacheExpression) ElementUtils.fromTypeMirror(com.oracle.truffle.dsl.processor.java.ElementUtils.fromTypeMirror) CodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror) 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) Call(com.oracle.truffle.dsl.processor.expression.DSLExpression.Call) DSLExpressionResolver(com.oracle.truffle.dsl.processor.expression.DSLExpressionResolver) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Variable(com.oracle.truffle.dsl.processor.expression.DSLExpression.Variable) LinkedHashSet(java.util.LinkedHashSet) HashSet(java.util.HashSet) CodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror) ArrayCodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror) Call(com.oracle.truffle.dsl.processor.expression.DSLExpression.Call) SpecializationData(com.oracle.truffle.dsl.processor.model.SpecializationData) ElementUtils.findAnnotationMirror(com.oracle.truffle.dsl.processor.java.ElementUtils.findAnnotationMirror) AnnotationMirror(javax.lang.model.element.AnnotationMirror) Parameter(com.oracle.truffle.dsl.processor.model.Parameter) ClassLiteral(com.oracle.truffle.dsl.processor.expression.DSLExpression.ClassLiteral) ClassLiteral(com.oracle.truffle.dsl.processor.expression.DSLExpression.ClassLiteral)

Example 4 with ElementUtils.findAnnotationMirror

use of com.oracle.truffle.dsl.processor.java.ElementUtils.findAnnotationMirror in project graal by oracle.

the class ExportsParser method parse.

@Override
protected ExportsData parse(Element element, List<AnnotationMirror> elementMirrors) {
    TypeElement type = (TypeElement) element;
    ExportsData model = parseExports(type, elementMirrors);
    if (model.hasErrors()) {
        return model;
    }
    // set of types that contribute members
    Set<TypeElement> declaringTypes = new HashSet<>();
    Set<TypeElement> declaringInTemplateTypes = new HashSet<>();
    declaringInTemplateTypes.add(type);
    for (ExportsLibrary library : model.getExportedLibraries().values()) {
        declaringTypes.addAll(library.getDeclaringTypes());
        if (library.isDeclaredInTemplate()) {
            declaringInTemplateTypes.addAll(library.getDeclaringTypes());
        }
    }
    Element packageElement = ElementUtils.findPackageElement(type);
    for (TypeElement currentType : declaringInTemplateTypes) {
        if (ElementUtils.elementEquals(currentType, element)) {
            // current type always visible
            continue;
        }
        List<Element> foundInvisibleMembers = new ArrayList<>();
        List<? extends Element> superTypeMembers = loadMembers(null, currentType);
        for (Element superTypeMember : superTypeMembers) {
            List<AnnotationMirror> exportedMessages = getRepeatedAnnotation(superTypeMember.getAnnotationMirrors(), types.ExportMessage);
            if (!exportedMessages.isEmpty()) {
                if (!ElementUtils.isVisible(packageElement, superTypeMember)) {
                    foundInvisibleMembers.add(superTypeMember);
                } else if (superTypeMember.getKind().isClass()) {
                    for (Element specializationMember : loadMembers(null, (TypeElement) superTypeMember)) {
                        if (ElementUtils.findAnnotationMirror(specializationMember, types.Specialization) != null && !ElementUtils.isVisible(packageElement, specializationMember)) {
                            foundInvisibleMembers.add(specializationMember);
                        }
                    }
                }
            }
        }
        if (!foundInvisibleMembers.isEmpty()) {
            StringBuilder b = new StringBuilder();
            for (Element invisibleMember : foundInvisibleMembers) {
                b.append(System.lineSeparator()).append("   - ");
                b.append(ElementUtils.getReadableReference(element, invisibleMember));
            }
            model.addError("Found invisible exported elements in super type '%s': %s%nIncrease their visibility to resolve this problem.", ElementUtils.getSimpleName(currentType), b.toString());
        }
    }
    if (model.getExportedLibraries().isEmpty()) {
        for (Element member : loadMembers(null, type)) {
            List<AnnotationMirror> exportedMessageMirrors = getRepeatedAnnotation(member.getAnnotationMirrors(), types.ExportMessage);
            if (!exportedMessageMirrors.isEmpty()) {
                model.addError(// 
                "Class declares @%s annotations but does not export any libraries. " + // 
                "Exported messages cannot be resoved without exported library. " + "Add @%s(MyLibrary.class) to the class ot resolve this.", getSimpleName(types.ExportMessage), getSimpleName(types.ExportLibrary));
                return model;
            }
        }
    }
    List<? extends Element> members = loadMembers(declaringInTemplateTypes, type);
    /*
         * First pass: element creation
         */
    Map<String, List<Element>> potentiallyMissedOverrides = new LinkedHashMap<>();
    List<ExportMessageData> exportedElements = new ArrayList<>();
    for (Element member : members) {
        List<AnnotationMirror> exportedMessageMirrors = getRepeatedAnnotation(member.getAnnotationMirrors(), types.ExportMessage);
        if (exportedMessageMirrors.isEmpty()) {
            boolean isMethod = isMethodElement(member);
            boolean isNode = isNodeElement(member);
            String name = null;
            if (isMethod) {
                name = member.getSimpleName().toString();
            } else if (isNode) {
                name = inferNodeMessageName((TypeElement) member);
            }
            if (isMethod || isNode) {
                Element enclosingType = member.getEnclosingElement();
                if (elementEquals(model.getTemplateType(), enclosingType)) {
                    potentiallyMissedOverrides.computeIfAbsent(name, (n) -> new ArrayList<>()).add(member);
                }
            }
        } else {
            for (AnnotationMirror exportMessage : exportedMessageMirrors) {
                exportedElements.addAll(parseExportedMessage(model, member, exportMessage));
            }
        }
    }
    for (ExportMessageData exportedMessage : exportedElements) {
        Element member = exportedMessage.getMessageElement();
        String messageName = exportedMessage.getResolvedMessage().getName();
        Map<String, ExportMessageData> exportedMessages = exportedMessage.getExportsLibrary().getExportedMessages();
        ExportMessageData existing = exportedMessages.get(messageName);
        if (existing != null) {
            Element existingEnclosingElement = existing.getMessageElement().getEnclosingElement();
            Element currentEnclosingElement = exportedMessage.getMessageElement().getEnclosingElement();
            if (ElementUtils.elementEquals(existingEnclosingElement, currentEnclosingElement)) {
                String error = String.format("Duplicate exported library message %s.", messageName);
                model.addError(member, error);
                model.addError(existing.getMessageElement(), error);
            } else if (ElementUtils.isSubtype(currentEnclosingElement.asType(), existingEnclosingElement.asType())) {
                // new message is more concrete
                exportedMessages.put(messageName, exportedMessage);
                existing.setOverriden(true);
            } else {
                // keep existing exported message
                exportedMessage.setOverriden(true);
            }
        } else {
            exportedMessages.put(messageName, exportedMessage);
        }
    }
    /*
         * Generate synthetic exports for export delegation.
         */
    for (ExportsLibrary exportsLibrary : model.getExportedLibraries().values()) {
        if (!exportsLibrary.hasExportDelegation()) {
            continue;
        }
        ExportMessageData accepts = exportsLibrary.getExportedMessages().get("accepts");
        if (accepts == null) {
            String delegateName = exportsLibrary.getDelegationVariable().getSimpleName().toString();
            CodeAnnotationMirror annotation = new CodeAnnotationMirror(types.CachedLibrary);
            annotation.setElementValue(ElementUtils.findExecutableElement(types.CachedLibrary, "value"), new CodeAnnotationValue("receiver_." + delegateName));
            CodeExecutableElement executable = CodeExecutableElement.clone(ElementUtils.findMethod(types.Library, "accepts"));
            executable.changeTypes(exportsLibrary.getReceiverType());
            executable.renameArguments("receiver_");
            executable.getModifiers().add(Modifier.STATIC);
            CodeVariableElement var = new CodeVariableElement(exportsLibrary.getLibrary().getTemplateType().asType(), delegateName);
            var.addAnnotationMirror(annotation);
            executable.setEnclosingElement(exportsLibrary.getTemplateType());
            executable.getParameters().add(var);
            LibraryMessage message = null;
            for (LibraryMessage libMessage : exportsLibrary.getLibrary().getMethods()) {
                if (libMessage.getName().equals("accepts")) {
                    message = libMessage;
                    break;
                }
            }
            accepts = new ExportMessageData(exportsLibrary, message, executable, annotation);
            exportsLibrary.getExportedMessages().put("accepts", accepts);
            exportedElements.add(accepts);
        } else {
            accepts.addError("Exporting a custom accepts method is currently not supported when export delegation is used in @%s. " + "Remove delegateTo from all exports or remove the accepts export to resolve this.", getSimpleName(types.ExportLibrary));
        }
    }
    for (ExportsLibrary exportsLibrary : model.getExportedLibraries().values()) {
        if (!exportsLibrary.isDeclaredInTemplate()) {
            for (ExportMessageData message : exportsLibrary.getExportedMessages().values()) {
                if (elementEquals(message.getMessageElement().getEnclosingElement(), type)) {
                    message.addError(// 
                    "The @%s declaration is missing for this exported message. " + "Add @%s(%s.class) to the enclosing class %s to resolve this.", getSimpleName(types.ExportLibrary), getSimpleName(types.ExportLibrary), getSimpleName(exportsLibrary.getLibrary().getTemplateType()), getSimpleName(type));
                }
            }
        }
    }
    // avoid removal of elements if errors occured.
    if (model.hasErrors()) {
        return model;
    }
    for (ExportsLibrary exportsLibrary : model.getExportedLibraries().values()) {
        if (exportsLibrary.isBuiltinDefaultExport()) {
            // we don't print unused warnings for builtin defaults.
            continue;
        }
        if (exportsLibrary.isDeclaredInTemplate()) {
            boolean foundDeclared = false;
            for (ExportMessageData message : exportsLibrary.getExportedMessages().values()) {
                if (message.isDeclared()) {
                    foundDeclared = true;
                    break;
                }
            }
            if (!foundDeclared) {
                exportsLibrary.addWarning("Exported library %s does not export any messages and therefore has no effect. Remove the export declaration to resolve this.", getSimpleName(exportsLibrary.getLibrary().getTemplateType()));
            }
        }
    }
    // avoid removal of elements if errors occured.
    if (model.hasErrors()) {
        return model;
    }
    /*
         * filter elements that come from exports not relevant for this class. Remove all export
         * declarations not relevant for this type.
         */
    Predicate<? super ExportsLibrary> filterpredicate = (library -> {
        if (library.isDynamicDispatchTarget()) {
            // Implicitly export super's library if dynamic dispatched.
            return true;
        }
        return library.isDeclaredInTemplate();
    });
    Set<ExportsLibrary> declaredExports = model.getExportedLibraries().values().stream().filter(filterpredicate).collect(Collectors.toSet());
    model.getExportedLibraries().values().removeIf((e) -> !declaredExports.contains(e));
    exportedElements = exportedElements.stream().filter((e) -> declaredExports.contains(e.getExportsLibrary())).collect(Collectors.toList());
    /*
         * Third pass: initialize and further parsing that need both method and node to be
         * available.
         */
    for (ExportsLibrary exportsLibrary : declaredExports) {
        // recreate cache for every exports library to not confuse exports configuration
        Map<String, NodeData> parsedNodeCache = new HashMap<>();
        for (ExportMessageData exportedElement : exportsLibrary.getExportedMessages().values()) {
            if (exportedElement.isOverriden()) {
                // gets confused.
                continue;
            }
            Element member = exportedElement.getMessageElement();
            if (isMethodElement(member)) {
                initializeExportedMethod(parsedNodeCache, model, exportedElement);
            } else if (isNodeElement(member)) {
                initializeExportedNode(parsedNodeCache, exportedElement);
            } else {
                throw new AssertionError("should not be reachable");
            }
        }
    }
    TypeMirror receiverClass = null;
    for (Entry<String, ExportsLibrary> entry : model.getExportedLibraries().entrySet()) {
        ExportsLibrary exportLib = entry.getValue();
        if (exportLib.hasErrors()) {
            continue;
        }
        if (receiverClass == null) {
            receiverClass = exportLib.getReceiverType();
        } else if (!typeEquals(exportLib.getReceiverType(), receiverClass)) {
            exportLib.addError("All receiver classes must match for a declared java type. Found '%s' and '%s'.", getSimpleName(receiverClass), getSimpleName(exportLib.getReceiverType()));
            continue;
        }
        Set<LibraryMessage> missingAbstractMessage = new LinkedHashSet<>();
        for (LibraryMessage message : exportLib.getLibrary().getMethods()) {
            List<Element> elementsWithSameName = potentiallyMissedOverrides.getOrDefault(message.getName(), Collections.emptyList());
            if (!elementsWithSameName.isEmpty()) {
                for (Element overridingElement : elementsWithSameName) {
                    if (ElementUtils.findAnnotationMirror(overridingElement, types.ExportMessage_Ignore) == null) {
                        exportLib.addError(overridingElement, "The method has the same name '%s' as a message in the exported library %s. Did you forget to export it? " + "Use @%s to export the message, @%s to ignore this warning, rename the method or reduce the visibility of the method to private to resolve this warning.", overridingElement.getSimpleName().toString(), getSimpleName(exportLib.getLibrary().getTemplateType()), types.ExportMessage.asElement().getSimpleName().toString(), types.ExportMessage_Ignore.asElement().getSimpleName().toString());
                    }
                }
            }
            if (message.isAbstract() && !message.getName().equals("accepts")) {
                ExportMessageData exportMessage = exportLib.getExportedMessages().get(message.getName());
                if (exportMessage == null || exportMessage.getResolvedMessage() != message) {
                    boolean isAbstract;
                    if (!message.getAbstractIfExported().isEmpty()) {
                        isAbstract = false;
                        for (LibraryMessage abstractIfExported : message.getAbstractIfExported()) {
                            if (exportLib.getExportedMessages().containsKey(abstractIfExported.getName())) {
                                isAbstract = true;
                                break;
                            }
                        }
                    } else {
                        isAbstract = !exportLib.hasExportDelegation();
                    }
                    if (isAbstract) {
                        missingAbstractMessage.add(message);
                    }
                }
            }
        }
        if (!missingAbstractMessage.isEmpty()) {
            StringBuilder msg = new StringBuilder(String.format("The following message(s) of library %s are abstract and must be exported using:%n", getSimpleName(exportLib.getLibrary().getTemplateType())));
            for (LibraryMessage message : missingAbstractMessage) {
                msg.append("  ").append(generateExpectedSignature(type, message, exportLib.getExplicitReceiver())).append(" {");
                if (!ElementUtils.isVoid(message.getExecutable().getReturnType())) {
                    msg.append(" return ").append(ElementUtils.defaultValue(message.getExecutable().getReturnType()));
                    msg.append(";");
                }
                msg.append(" }%n");
            }
            exportLib.addError(msg.toString());
        }
    }
    for (ExportsLibrary libraryExports : model.getExportedLibraries().values()) {
        List<NodeData> cachedSharedNodes = new ArrayList<>();
        List<ExportMessageData> exportedMessages = new ArrayList<>();
        for (ExportMessageData export : libraryExports.getExportedMessages().values()) {
            if (export.getSpecializedNode() != null) {
                cachedSharedNodes.add(export.getSpecializedNode());
                exportedMessages.add(export);
            }
        }
        libraryExports.setSharedExpressions(NodeParser.computeSharing(libraryExports.getTemplateType(), cachedSharedNodes, true));
        // JDT will otherwise just ignore those messages and not display anything.
        for (int i = 0; i < cachedSharedNodes.size(); i++) {
            NodeData nodeData = cachedSharedNodes.get(i);
            ExportMessageData exportedMessage = exportedMessages.get(i);
            if (nodeData.hasErrorsOrWarnings()) {
                nodeData.redirectMessagesOnGeneratedElements(exportedMessage);
            }
            nodeData.setGenerateUncached(false);
        }
    }
    for (ExportMessageData message : exportedElements) {
        if (!elementEquals(message.getMessageElement().getEnclosingElement(), model.getTemplateType())) {
            message.redirectMessages(message.getExportsLibrary());
        }
    }
    if (isGenerateSlowPathOnly(type)) {
        for (ExportsLibrary libraryExports : model.getExportedLibraries().values()) {
            for (ExportMessageData export : libraryExports.getExportedMessages().values()) {
                if (export.isClass() && export.getSpecializedNode() != null) {
                    NodeParser.removeFastPathSpecializations(export.getSpecializedNode());
                }
            }
        }
    }
    return model;
}
Also used : Arrays(java.util.Arrays) Modifier(javax.lang.model.element.Modifier) TypeElement(javax.lang.model.element.TypeElement) ElementUtils.getRepeatedAnnotation(com.oracle.truffle.dsl.processor.java.ElementUtils.getRepeatedAnnotation) ElementUtils.getSimpleName(com.oracle.truffle.dsl.processor.java.ElementUtils.getSimpleName) ElementUtils.getQualifiedName(com.oracle.truffle.dsl.processor.java.ElementUtils.getQualifiedName) Map(java.util.Map) ElementUtils.getTypeId(com.oracle.truffle.dsl.processor.java.ElementUtils.getTypeId) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) ElementUtils.firstLetterUpperCase(com.oracle.truffle.dsl.processor.java.ElementUtils.firstLetterUpperCase) NodeData(com.oracle.truffle.dsl.processor.model.NodeData) CodeExecutableElement(com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement) ElementUtils.getSuperType(com.oracle.truffle.dsl.processor.java.ElementUtils.getSuperType) CodeTypeElement(com.oracle.truffle.dsl.processor.java.model.CodeTypeElement) Predicate(java.util.function.Predicate) Collection(java.util.Collection) Set(java.util.Set) Element(javax.lang.model.element.Element) Collectors(java.util.stream.Collectors) TypeKind(javax.lang.model.type.TypeKind) List(java.util.List) Entry(java.util.Map.Entry) ElementUtils.isAssignable(com.oracle.truffle.dsl.processor.java.ElementUtils.isAssignable) AnnotationValue(javax.lang.model.element.AnnotationValue) DSLExpression(com.oracle.truffle.dsl.processor.expression.DSLExpression) NodeParser(com.oracle.truffle.dsl.processor.parser.NodeParser) VariableElement(javax.lang.model.element.VariableElement) HashMap(java.util.HashMap) ElementUtils.fromTypeMirror(com.oracle.truffle.dsl.processor.java.ElementUtils.fromTypeMirror) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) LinkedHashMap(java.util.LinkedHashMap) ElementUtils.findAnnotationMirror(com.oracle.truffle.dsl.processor.java.ElementUtils.findAnnotationMirror) CompilerFactory(com.oracle.truffle.dsl.processor.java.compiler.CompilerFactory) ElementUtils.isSubtype(com.oracle.truffle.dsl.processor.java.ElementUtils.isSubtype) ElementUtils.typeEquals(com.oracle.truffle.dsl.processor.java.ElementUtils.typeEquals) DeclaredType(javax.lang.model.type.DeclaredType) InvalidExpressionException(com.oracle.truffle.dsl.processor.expression.InvalidExpressionException) ElementUtils.getAnnotationValue(com.oracle.truffle.dsl.processor.java.ElementUtils.getAnnotationValue) GeneratorUtils(com.oracle.truffle.dsl.processor.generator.GeneratorUtils) ElementFilter(javax.lang.model.util.ElementFilter) LinkedHashSet(java.util.LinkedHashSet) ElementUtils(com.oracle.truffle.dsl.processor.java.ElementUtils) AbstractParser(com.oracle.truffle.dsl.processor.parser.AbstractParser) CodeAnnotationMirror(com.oracle.truffle.dsl.processor.java.model.CodeAnnotationMirror) Iterator(java.util.Iterator) ElementKind(javax.lang.model.element.ElementKind) ElementUtils.elementEquals(com.oracle.truffle.dsl.processor.java.ElementUtils.elementEquals) PUBLIC(javax.lang.model.element.Modifier.PUBLIC) ExecutableElement(javax.lang.model.element.ExecutableElement) ProcessorContext(com.oracle.truffle.dsl.processor.ProcessorContext) CodeAnnotationValue(com.oracle.truffle.dsl.processor.java.model.CodeAnnotationValue) AnnotationMirror(javax.lang.model.element.AnnotationMirror) CodeNames(com.oracle.truffle.dsl.processor.java.model.CodeNames) STATIC(javax.lang.model.element.Modifier.STATIC) TypeMirror(javax.lang.model.type.TypeMirror) ElementUtils.modifiers(com.oracle.truffle.dsl.processor.java.ElementUtils.modifiers) ElementUtils.firstLetterLowerCase(com.oracle.truffle.dsl.processor.java.ElementUtils.firstLetterLowerCase) Collections(java.util.Collections) DSLExpressionResolver(com.oracle.truffle.dsl.processor.expression.DSLExpressionResolver) LinkedHashSet(java.util.LinkedHashSet) CodeExecutableElement(com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) TypeElement(javax.lang.model.element.TypeElement) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) CodeExecutableElement(com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement) CodeTypeElement(com.oracle.truffle.dsl.processor.java.model.CodeTypeElement) Element(javax.lang.model.element.Element) VariableElement(javax.lang.model.element.VariableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) ElementUtils.fromTypeMirror(com.oracle.truffle.dsl.processor.java.ElementUtils.fromTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) List(java.util.List) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) LinkedHashSet(java.util.LinkedHashSet) CodeAnnotationMirror(com.oracle.truffle.dsl.processor.java.model.CodeAnnotationMirror) TypeElement(javax.lang.model.element.TypeElement) CodeTypeElement(com.oracle.truffle.dsl.processor.java.model.CodeTypeElement) CodeAnnotationValue(com.oracle.truffle.dsl.processor.java.model.CodeAnnotationValue) NodeData(com.oracle.truffle.dsl.processor.model.NodeData) ElementUtils.findAnnotationMirror(com.oracle.truffle.dsl.processor.java.ElementUtils.findAnnotationMirror) CodeAnnotationMirror(com.oracle.truffle.dsl.processor.java.model.CodeAnnotationMirror) AnnotationMirror(javax.lang.model.element.AnnotationMirror)

Example 5 with ElementUtils.findAnnotationMirror

use of com.oracle.truffle.dsl.processor.java.ElementUtils.findAnnotationMirror in project graal by oracle.

the class FlatNodeGenFactory method create.

public CodeTypeElement create(CodeTypeElement clazz) {
    if (primaryNode) {
        for (NodeChildData child : node.getChildren()) {
            clazz.addOptional(createAccessChildMethod(child, false));
        }
        for (NodeFieldData field : node.getFields()) {
            if (!field.isGenerated()) {
                continue;
            }
            Set<Modifier> fieldModifiers;
            if (field.isSettable()) {
                fieldModifiers = modifiers(PRIVATE);
            } else {
                fieldModifiers = modifiers(PRIVATE, FINAL);
            }
            clazz.add(new CodeVariableElement(fieldModifiers, field.getType(), field.getName()));
            if (field.getGetter() != null && field.getGetter().getModifiers().contains(Modifier.ABSTRACT)) {
                CodeExecutableElement method = CodeExecutableElement.clone(field.getGetter());
                method.getModifiers().remove(Modifier.ABSTRACT);
                method.createBuilder().startReturn().string("this.").string(field.getName()).end();
                clazz.add(method);
            }
            if (field.isSettable()) {
                CodeExecutableElement method = CodeExecutableElement.clone(field.getSetter());
                method.renameArguments(field.getName());
                method.getModifiers().remove(Modifier.ABSTRACT);
                method.createBuilder().startStatement().string("this.").string(field.getName()).string(" = ", field.getName()).end();
                clazz.add(method);
            }
        }
        for (ExecutableElement superConstructor : GeneratorUtils.findUserConstructors(node.getTemplateType().asType())) {
            clazz.add(createNodeConstructor(clazz, superConstructor));
        }
        for (NodeExecutionData execution : node.getChildExecutions()) {
            if (execution.getChild() != null && execution.getChild().needsGeneratedField()) {
                clazz.add(createNodeField(PRIVATE, execution.getNodeType(), nodeFieldName(execution), types.Node_Child));
            }
        }
    }
    createFields(clazz);
    TypeMirror genericReturnType = node.getPolymorphicExecutable().getReturnType();
    List<ExecutableTypeData> executableTypes = filterExecutableTypes(node.getExecutableTypes(), reachableSpecializations);
    List<ExecutableTypeData> genericExecutableTypes = new ArrayList<>();
    List<ExecutableTypeData> specializedExecutableTypes = new ArrayList<>();
    List<ExecutableTypeData> voidExecutableTypes = new ArrayList<>();
    for (ExecutableTypeData type : executableTypes) {
        if (isVoid(type.getReturnType())) {
            voidExecutableTypes.add(type);
        } else if (type.hasUnexpectedValue() && !typeEquals(genericReturnType, type.getReturnType())) {
            specializedExecutableTypes.add(type);
        } else {
            genericExecutableTypes.add(type);
        }
    }
    if (genericExecutableTypes.size() > 1) {
        boolean hasGenericTypeMatch = false;
        for (ExecutableTypeData genericExecutable : genericExecutableTypes) {
            if (typeEquals(genericExecutable.getReturnType(), genericReturnType)) {
                hasGenericTypeMatch = true;
                break;
            }
        }
        if (hasGenericTypeMatch) {
            for (ListIterator<ExecutableTypeData> iterator = genericExecutableTypes.listIterator(); iterator.hasNext(); ) {
                ExecutableTypeData executableTypeData = iterator.next();
                if (!isAssignable(genericReturnType, executableTypeData.getReturnType())) {
                    iterator.remove();
                    specializedExecutableTypes.add(executableTypeData);
                }
            }
        }
    }
    SpecializationData fallback = node.getFallbackSpecialization();
    if (fallback.getMethod() != null && fallback.isReachable()) {
        clazz.add(createFallbackGuard());
    }
    for (ExecutableTypeData type : genericExecutableTypes) {
        wrapWithTraceOnReturn(createExecute(clazz, type, Collections.<ExecutableTypeData>emptyList()));
    }
    for (ExecutableTypeData type : specializedExecutableTypes) {
        wrapWithTraceOnReturn(createExecute(clazz, type, genericExecutableTypes));
    }
    for (ExecutableTypeData type : voidExecutableTypes) {
        List<ExecutableTypeData> genericAndSpecialized = new ArrayList<>();
        genericAndSpecialized.addAll(genericExecutableTypes);
        genericAndSpecialized.addAll(specializedExecutableTypes);
        wrapWithTraceOnReturn(createExecute(clazz, type, genericAndSpecialized));
    }
    clazz.addOptional(createExecuteAndSpecialize());
    final ReportPolymorphismAction reportPolymorphismAction = reportPolymorphismAction(node, reachableSpecializations);
    if (reportPolymorphismAction.required()) {
        clazz.addOptional(createCheckForPolymorphicSpecialize(reportPolymorphismAction));
        if (requiresCacheCheck(reportPolymorphismAction)) {
            clazz.addOptional(createCountCaches());
        }
    }
    AnnotationMirror nodeInfo = null;
    try {
        nodeInfo = ElementUtils.findAnnotationMirror(node.getTemplateType(), types.NodeInfo);
    } catch (UnsupportedOperationException e) {
    }
    String cost = nodeInfo != null ? ElementUtils.getAnnotationValue(VariableElement.class, nodeInfo, "cost").getSimpleName().toString() : null;
    if ((cost == null || cost.equals("MONOMORPHIC")) && isUndeclaredOrOverrideable(clazz, "getCost")) {
        if (primaryNode) {
            clazz.add(createGetCostMethod(false));
        }
    }
    for (TypeMirror type : uniqueSortedTypes(expectedTypes, false)) {
        if (!typeSystem.hasType(type)) {
            clazz.addOptional(TypeSystemCodeGenerator.createExpectMethod(PRIVATE, typeSystem, context.getType(Object.class), type));
        }
    }
    clazz.getEnclosedElements().addAll(removeThisMethods.values());
    for (SpecializationData specialization : specializationClasses.keySet()) {
        CodeTypeElement type = specializationClasses.get(specialization);
        if (getInsertAccessorSet(true).contains(specialization)) {
            type.add(createInsertAccessor(true));
        }
        if (getInsertAccessorSet(false).contains(specialization)) {
            type.add(createInsertAccessor(false));
        }
    }
    if (isGenerateIntrospection()) {
        generateIntrospectionInfo(clazz);
    }
    if (isGenerateAOT()) {
        generateAOT(clazz);
    }
    if (node.isUncachable() && node.isGenerateUncached()) {
        CodeTypeElement uncached = GeneratorUtils.createClass(node, null, modifiers(PRIVATE, STATIC, FINAL), "Uncached", node.getTemplateType().asType());
        uncached.getEnclosedElements().addAll(createUncachedFields());
        for (NodeFieldData field : node.getFields()) {
            if (!field.isGenerated()) {
                continue;
            }
            if (field.getGetter() != null && field.getGetter().getModifiers().contains(Modifier.ABSTRACT)) {
                CodeExecutableElement method = CodeExecutableElement.clone(field.getGetter());
                method.getModifiers().remove(Modifier.ABSTRACT);
                method.createBuilder().startThrow().startNew(context.getType(UnsupportedOperationException.class)).end().end();
                uncached.add(method);
            }
            if (field.isSettable()) {
                CodeExecutableElement method = CodeExecutableElement.clone(field.getSetter());
                method.getModifiers().remove(Modifier.ABSTRACT);
                method.createBuilder().startThrow().startNew(context.getType(UnsupportedOperationException.class)).end().end();
                uncached.add(method);
            }
        }
        generateStatisticsFields(uncached);
        for (NodeChildData child : node.getChildren()) {
            uncached.addOptional(createAccessChildMethod(child, true));
        }
        for (ExecutableTypeData type : genericExecutableTypes) {
            wrapWithTraceOnReturn(uncached.add(createUncachedExecute(type)));
        }
        for (ExecutableTypeData type : specializedExecutableTypes) {
            wrapWithTraceOnReturn(uncached.add(createUncachedExecute(type)));
        }
        for (ExecutableTypeData type : voidExecutableTypes) {
            wrapWithTraceOnReturn(uncached.add(createUncachedExecute(type)));
        }
        if ((cost == null || cost.equals("MONOMORPHIC")) && isUndeclaredOrOverrideable(uncached, "getCost")) {
            uncached.add(createGetCostMethod(true));
        }
        CodeExecutableElement isAdoptable = CodeExecutableElement.cloneNoAnnotations(ElementUtils.findExecutableElement(types.Node, "isAdoptable"));
        isAdoptable.createBuilder().returnFalse();
        uncached.add(isAdoptable);
        clazz.add(uncached);
        GeneratedTypeMirror uncachedType = new GeneratedTypeMirror("", uncached.getSimpleName().toString());
        CodeVariableElement uncachedField = clazz.add(new CodeVariableElement(modifiers(PRIVATE, STATIC, FINAL), uncachedType, "UNCACHED"));
        uncachedField.createInitBuilder().startNew(uncachedType).end();
    }
    return clazz;
}
Also used : ExecutableTypeData(com.oracle.truffle.dsl.processor.model.ExecutableTypeData) CodeExecutableElement(com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement) NodeChildData(com.oracle.truffle.dsl.processor.model.NodeChildData) NodeExecutionData(com.oracle.truffle.dsl.processor.model.NodeExecutionData) CodeExecutableElement(com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement) ExecutableElement(javax.lang.model.element.ExecutableElement) GeneratedTypeMirror(com.oracle.truffle.dsl.processor.java.model.GeneratedTypeMirror) ArrayList(java.util.ArrayList) SpecializationData(com.oracle.truffle.dsl.processor.model.SpecializationData) VariableElement(javax.lang.model.element.VariableElement) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) ElementUtils.findAnnotationMirror(com.oracle.truffle.dsl.processor.java.ElementUtils.findAnnotationMirror) AnnotationMirror(javax.lang.model.element.AnnotationMirror) CodeAnnotationMirror(com.oracle.truffle.dsl.processor.java.model.CodeAnnotationMirror) NodeFieldData(com.oracle.truffle.dsl.processor.model.NodeFieldData) DeclaredCodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.DeclaredCodeTypeMirror) ArrayCodeTypeMirror(com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror) GeneratedTypeMirror(com.oracle.truffle.dsl.processor.java.model.GeneratedTypeMirror) TypeMirror(javax.lang.model.type.TypeMirror) CodeTypeElement(com.oracle.truffle.dsl.processor.java.model.CodeTypeElement) CodeVariableElement(com.oracle.truffle.dsl.processor.java.model.CodeVariableElement) Modifier(javax.lang.model.element.Modifier)

Aggregations

ElementUtils.findAnnotationMirror (com.oracle.truffle.dsl.processor.java.ElementUtils.findAnnotationMirror)7 ArrayList (java.util.ArrayList)7 AnnotationMirror (javax.lang.model.element.AnnotationMirror)7 TypeMirror (javax.lang.model.type.TypeMirror)7 ElementUtils.fromTypeMirror (com.oracle.truffle.dsl.processor.java.ElementUtils.fromTypeMirror)6 CodeVariableElement (com.oracle.truffle.dsl.processor.java.model.CodeVariableElement)6 VariableElement (javax.lang.model.element.VariableElement)6 CodeTypeElement (com.oracle.truffle.dsl.processor.java.model.CodeTypeElement)5 ArrayCodeTypeMirror (com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror.ArrayCodeTypeMirror)5 CodeExecutableElement (com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement)4 CodeTypeMirror (com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror)4 HashSet (java.util.HashSet)4 LinkedHashSet (java.util.LinkedHashSet)4 ExecutableElement (javax.lang.model.element.ExecutableElement)4 SpecializationData (com.oracle.truffle.dsl.processor.model.SpecializationData)3 List (java.util.List)3 TypeElement (javax.lang.model.element.TypeElement)3 DSLExpression (com.oracle.truffle.dsl.processor.expression.DSLExpression)2 DSLExpressionResolver (com.oracle.truffle.dsl.processor.expression.DSLExpressionResolver)2 ElementUtils.getAnnotationValue (com.oracle.truffle.dsl.processor.java.ElementUtils.getAnnotationValue)2