331 final String nodePackage;
332
333 /**
334 * The matchable inputs of the node.
335 */
336 final List<String> inputs;
337
338 /**
339 * Should swapped variants of this match be generated. The user of the match is expected to
340 * compensate for any ordering differences in compare which are commutative but require
341 * reinterpreting the condition in that case.
342 */
343 final boolean commutative;
344
345 /**
346 * Can multiple users of this node subsume it. Constants can be swallowed into a match even
347 * if there are multiple users.
348 */
349 final boolean shareable;
350
351 final Set<Element> originatingElements = new HashSet<>();
352
353 TypeDescriptor(TypeMirror mirror, String shortName, String nodeClass, String nodePackage, List<String> inputs, boolean commutative, boolean shareable) {
354 this.mirror = mirror;
355 this.shortName = shortName;
356 this.nodeClass = nodeClass;
357 this.nodePackage = nodePackage;
358 this.inputs = inputs;
359 this.commutative = commutative;
360 this.shareable = shareable;
361 assert !commutative || inputs.size() == 2;
362 }
363 }
364
365 /**
366 * The types which are know for purpose of parsing MatchRule expressions.
367 */
368 Map<String, TypeDescriptor> knownTypes = new HashMap<>();
369
370 private TypeDescriptor valueType;
371
372 private void declareType(TypeMirror mirror, String shortName, String nodeClass, String nodePackage, List<String> inputs, boolean commutative, boolean shareable, Element element) {
373 TypeDescriptor descriptor = new TypeDescriptor(mirror, shortName, nodeClass, nodePackage, inputs, commutative, shareable);
374 descriptor.originatingElements.add(element);
375 knownTypes.put(shortName, descriptor);
376 }
377
378 private String findPackage(Element type) {
379 PackageElement p = processingEnv.getElementUtils().getPackageOf(type);
380 if (p != null) {
381 return p.getQualifiedName().toString();
382 }
383 throw new InternalError("Can't find package for " + type);
384 }
385
386 class MatchDescriptor {
387 TypeDescriptor nodeType;
388 String name;
389 MatchDescriptor[] inputs;
390
391 MatchDescriptor(TypeDescriptor nodeType, String name, boolean forExpression) {
392 this.nodeType = nodeType;
393 this.name = name;
436 * @return a list of Strings which will construct pattern matchers for this rule.
437 */
438 List<String> generateVariants() {
439 String prefix = formatPrefix();
440 String suffix = formatSuffix();
441 ArrayList<String> variants = new ArrayList<>();
442 if (inputs.length > 0) {
443 for (String var : recurseVariants(0)) {
444 variants.add(prefix + ", " + var + suffix);
445 }
446 } else {
447 assert inputs.length == 0;
448 variants.add(prefix + suffix);
449 }
450
451 return variants;
452 }
453
454 private String formatPrefix() {
455 if (nodeType == valueType) {
456 return String.format("new MatchPattern(%s, false", name != null ? ("\"" + name + "\"") : "null");
457 } else {
458 return String.format("new MatchPattern(%s.class, %s", nodeType.nodeClass, name != null ? ("\"" + name + "\"") : "null");
459 }
460 }
461
462 private String formatSuffix() {
463 if (nodeType != null) {
464 if (inputs.length != nodeType.inputs.size()) {
465 return ", true)";
466 } else {
467 if (nodeType.inputs.size() > 0) {
468 return ", " + nodeType.nodeClass + "_positions, " + !nodeType.shareable + ")";
469 }
470 if (nodeType.shareable) {
471 return ", false)";
472 }
473 }
474 }
475 return ")";
476 }
477
478 String generatePositionDeclaration() {
479 return String.format("Position[] %s_positions = MatchRuleRegistry.findPositions(%s.TYPE, new String[]{\"%s\"});", nodeType.nodeClass, nodeType.nodeClass,
480 String.join("\", \"", nodeType.inputs));
481 }
482 }
483
484 /**
485 * Strip the package off a class name leaving the full class name including any outer classes.
486 */
487 private String fullClassName(Element element) {
488 String pkg = findPackage(element);
489 return ((TypeElement) element).getQualifiedName().toString().substring(pkg.length() + 1);
490 }
491
704 TypeMirror matchRuleTypeMirror = matchRuleTypeElement.asType();
705
706 TypeElement matchableNodeTypeElement = getTypeElement(MATCHABLE_NODE_CLASS_NAME);
707 TypeElement matchableNodesTypeElement = getTypeElement(MATCHABLE_NODES_CLASS_NAME);
708
709 currentRound = roundEnv;
710 try {
711 for (Element element : roundEnv.getElementsAnnotatedWith(matchableNodeTypeElement)) {
712 currentElement = element;
713 logMessage("%s\n", element);
714 processMatchableNodes(element);
715 }
716 for (Element element : roundEnv.getElementsAnnotatedWith(matchableNodesTypeElement)) {
717 currentElement = element;
718 logMessage("%s\n", element);
719 processMatchableNodes(element);
720 }
721 // Define a TypeDescriptor for the generic node but don't enter it into the nodeTypes
722 // table since it shouldn't be mentioned in match rules.
723 TypeMirror valueTypeMirror = getTypeElement(VALUE_NODE_CLASS_NAME).asType();
724 valueType = new TypeDescriptor(valueTypeMirror, "Value", "ValueNode", "org.graalvm.compiler.nodes", Collections.emptyList(), false, false);
725
726 Map<TypeElement, MatchRuleDescriptor> map = new HashMap<>();
727
728 for (Element element : roundEnv.getElementsAnnotatedWith(matchRuleTypeElement)) {
729 currentElement = element;
730 AnnotationMirror matchRule = getAnnotation(element, matchRuleTypeMirror);
731 List<AnnotationMirror> matchRuleAnnotations = Collections.singletonList(matchRule);
732 processMatchRules(map, element, matchRuleAnnotations);
733 }
734 for (Element element : roundEnv.getElementsAnnotatedWith(matchRulesTypeElement)) {
735 currentElement = element;
736 AnnotationMirror matchRules = getAnnotation(element, matchRulesTypeMirror);
737 List<AnnotationMirror> matchRuleAnnotations = getAnnotationValueList(matchRules, "value", AnnotationMirror.class);
738 processMatchRules(map, element, matchRuleAnnotations);
739 }
740
741 currentElement = null;
742 for (MatchRuleDescriptor info : map.values()) {
743 createFiles(info);
744 }
814 for (String input : inputs) {
815 boolean ok = false;
816 TypeElement current = nodeClassElement;
817 while (!ok && current != null) {
818 for (Element fieldElement : ElementFilter.fieldsIn(current.getEnclosedElements())) {
819 if (fieldElement.getSimpleName().toString().equals(input)) {
820 ok = true;
821 break;
822 }
823 }
824 TypeMirror theSuper = current.getSuperclass();
825 current = (TypeElement) typeUtils.asElement(theSuper);
826 }
827 if (!ok) {
828 printError(element, matchable, "Input named \"%s\" doesn't exist in %s", input, nodeClassElement.getSimpleName());
829 }
830 }
831
832 boolean commutative = getAnnotationValue(matchable, "commutative", Boolean.class);
833 boolean shareable = getAnnotationValue(matchable, "shareable", Boolean.class);
834 declareType(nodeClassMirror, shortName, nodeClass, nodePackage, inputs, commutative, shareable, element);
835 }
836
837 private void processMatchRules(Map<TypeElement, MatchRuleDescriptor> map, Element element, List<AnnotationMirror> matchRules) {
838 if (!processedMatchRules.contains(element)) {
839 try {
840 processedMatchRules.add(element);
841
842 // The annotation element type should ensure this is true.
843 assert element instanceof ExecutableElement;
844
845 findMatchableNodes(element);
846
847 TypeElement topDeclaringType = topDeclaringType(element);
848 MatchRuleDescriptor info = map.get(topDeclaringType);
849 if (info == null) {
850 info = new MatchRuleDescriptor(topDeclaringType);
851 map.put(topDeclaringType, info);
852 }
853 for (AnnotationMirror matchRule : matchRules) {
854 processMatchRule((ExecutableElement) element, info, matchRule);
|
331 final String nodePackage;
332
333 /**
334 * The matchable inputs of the node.
335 */
336 final List<String> inputs;
337
338 /**
339 * Should swapped variants of this match be generated. The user of the match is expected to
340 * compensate for any ordering differences in compare which are commutative but require
341 * reinterpreting the condition in that case.
342 */
343 final boolean commutative;
344
345 /**
346 * Can multiple users of this node subsume it. Constants can be swallowed into a match even
347 * if there are multiple users.
348 */
349 final boolean shareable;
350
351 /**
352 * Can this node be subsumed into a match even if there are side effecting nodes between
353 * this node and the match.
354 */
355 final boolean ignoresSideEffects;
356
357 final Set<Element> originatingElements = new HashSet<>();
358
359 TypeDescriptor(TypeMirror mirror, String shortName, String nodeClass, String nodePackage, List<String> inputs, boolean commutative, boolean shareable, boolean ignoresSideEffects) {
360 this.mirror = mirror;
361 this.shortName = shortName;
362 this.nodeClass = nodeClass;
363 this.nodePackage = nodePackage;
364 this.inputs = inputs;
365 this.commutative = commutative;
366 this.shareable = shareable;
367 this.ignoresSideEffects = ignoresSideEffects;
368 assert !commutative || inputs.size() == 2;
369 }
370 }
371
372 /**
373 * The types which are know for purpose of parsing MatchRule expressions.
374 */
375 Map<String, TypeDescriptor> knownTypes = new HashMap<>();
376
377 private TypeDescriptor valueType;
378
379 private void declareType(TypeMirror mirror, String shortName, String nodeClass, String nodePackage, List<String> inputs, boolean commutative, boolean shareable, boolean ignoresSideEffects,
380 Element element) {
381 TypeDescriptor descriptor = new TypeDescriptor(mirror, shortName, nodeClass, nodePackage, inputs, commutative, shareable, ignoresSideEffects);
382 descriptor.originatingElements.add(element);
383 knownTypes.put(shortName, descriptor);
384 }
385
386 private String findPackage(Element type) {
387 PackageElement p = processingEnv.getElementUtils().getPackageOf(type);
388 if (p != null) {
389 return p.getQualifiedName().toString();
390 }
391 throw new InternalError("Can't find package for " + type);
392 }
393
394 class MatchDescriptor {
395 TypeDescriptor nodeType;
396 String name;
397 MatchDescriptor[] inputs;
398
399 MatchDescriptor(TypeDescriptor nodeType, String name, boolean forExpression) {
400 this.nodeType = nodeType;
401 this.name = name;
444 * @return a list of Strings which will construct pattern matchers for this rule.
445 */
446 List<String> generateVariants() {
447 String prefix = formatPrefix();
448 String suffix = formatSuffix();
449 ArrayList<String> variants = new ArrayList<>();
450 if (inputs.length > 0) {
451 for (String var : recurseVariants(0)) {
452 variants.add(prefix + ", " + var + suffix);
453 }
454 } else {
455 assert inputs.length == 0;
456 variants.add(prefix + suffix);
457 }
458
459 return variants;
460 }
461
462 private String formatPrefix() {
463 if (nodeType == valueType) {
464 return String.format("new MatchPattern(%s, false, false", name != null ? ("\"" + name + "\"") : "null");
465 } else {
466 return String.format("new MatchPattern(%s.class, %s", nodeType.nodeClass, name != null ? ("\"" + name + "\"") : "null");
467 }
468 }
469
470 private String formatSuffix() {
471 if (nodeType != null) {
472 if (inputs.length != nodeType.inputs.size()) {
473 return ", true, " + nodeType.ignoresSideEffects + ")";
474 } else {
475 if (nodeType.inputs.size() > 0) {
476 return ", " + nodeType.nodeClass + "_positions, " + !nodeType.shareable + ", " + nodeType.ignoresSideEffects + ")";
477 }
478 if (nodeType.shareable) {
479 return ", false, " + nodeType.ignoresSideEffects + ")";
480 }
481 }
482 }
483 return ")";
484 }
485
486 String generatePositionDeclaration() {
487 return String.format("Position[] %s_positions = MatchRuleRegistry.findPositions(%s.TYPE, new String[]{\"%s\"});", nodeType.nodeClass, nodeType.nodeClass,
488 String.join("\", \"", nodeType.inputs));
489 }
490 }
491
492 /**
493 * Strip the package off a class name leaving the full class name including any outer classes.
494 */
495 private String fullClassName(Element element) {
496 String pkg = findPackage(element);
497 return ((TypeElement) element).getQualifiedName().toString().substring(pkg.length() + 1);
498 }
499
712 TypeMirror matchRuleTypeMirror = matchRuleTypeElement.asType();
713
714 TypeElement matchableNodeTypeElement = getTypeElement(MATCHABLE_NODE_CLASS_NAME);
715 TypeElement matchableNodesTypeElement = getTypeElement(MATCHABLE_NODES_CLASS_NAME);
716
717 currentRound = roundEnv;
718 try {
719 for (Element element : roundEnv.getElementsAnnotatedWith(matchableNodeTypeElement)) {
720 currentElement = element;
721 logMessage("%s\n", element);
722 processMatchableNodes(element);
723 }
724 for (Element element : roundEnv.getElementsAnnotatedWith(matchableNodesTypeElement)) {
725 currentElement = element;
726 logMessage("%s\n", element);
727 processMatchableNodes(element);
728 }
729 // Define a TypeDescriptor for the generic node but don't enter it into the nodeTypes
730 // table since it shouldn't be mentioned in match rules.
731 TypeMirror valueTypeMirror = getTypeElement(VALUE_NODE_CLASS_NAME).asType();
732 valueType = new TypeDescriptor(valueTypeMirror, "Value", "ValueNode", "org.graalvm.compiler.nodes", Collections.emptyList(), false, false, false);
733
734 Map<TypeElement, MatchRuleDescriptor> map = new HashMap<>();
735
736 for (Element element : roundEnv.getElementsAnnotatedWith(matchRuleTypeElement)) {
737 currentElement = element;
738 AnnotationMirror matchRule = getAnnotation(element, matchRuleTypeMirror);
739 List<AnnotationMirror> matchRuleAnnotations = Collections.singletonList(matchRule);
740 processMatchRules(map, element, matchRuleAnnotations);
741 }
742 for (Element element : roundEnv.getElementsAnnotatedWith(matchRulesTypeElement)) {
743 currentElement = element;
744 AnnotationMirror matchRules = getAnnotation(element, matchRulesTypeMirror);
745 List<AnnotationMirror> matchRuleAnnotations = getAnnotationValueList(matchRules, "value", AnnotationMirror.class);
746 processMatchRules(map, element, matchRuleAnnotations);
747 }
748
749 currentElement = null;
750 for (MatchRuleDescriptor info : map.values()) {
751 createFiles(info);
752 }
822 for (String input : inputs) {
823 boolean ok = false;
824 TypeElement current = nodeClassElement;
825 while (!ok && current != null) {
826 for (Element fieldElement : ElementFilter.fieldsIn(current.getEnclosedElements())) {
827 if (fieldElement.getSimpleName().toString().equals(input)) {
828 ok = true;
829 break;
830 }
831 }
832 TypeMirror theSuper = current.getSuperclass();
833 current = (TypeElement) typeUtils.asElement(theSuper);
834 }
835 if (!ok) {
836 printError(element, matchable, "Input named \"%s\" doesn't exist in %s", input, nodeClassElement.getSimpleName());
837 }
838 }
839
840 boolean commutative = getAnnotationValue(matchable, "commutative", Boolean.class);
841 boolean shareable = getAnnotationValue(matchable, "shareable", Boolean.class);
842 boolean ignoresSideEffects = getAnnotationValue(matchable, "ignoresSideEffects", Boolean.class);
843 declareType(nodeClassMirror, shortName, nodeClass, nodePackage, inputs, commutative, shareable, ignoresSideEffects, element);
844 }
845
846 private void processMatchRules(Map<TypeElement, MatchRuleDescriptor> map, Element element, List<AnnotationMirror> matchRules) {
847 if (!processedMatchRules.contains(element)) {
848 try {
849 processedMatchRules.add(element);
850
851 // The annotation element type should ensure this is true.
852 assert element instanceof ExecutableElement;
853
854 findMatchableNodes(element);
855
856 TypeElement topDeclaringType = topDeclaringType(element);
857 MatchRuleDescriptor info = map.get(topDeclaringType);
858 if (info == null) {
859 info = new MatchRuleDescriptor(topDeclaringType);
860 map.put(topDeclaringType, info);
861 }
862 for (AnnotationMirror matchRule : matchRules) {
863 processMatchRule((ExecutableElement) element, info, matchRule);
|