Mercurial > hg > graal-compiler
comparison graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java @ 7855:6e4fb0ccebb1
Generated factories implement the new NodeFactory interface.
author | Christian Humer <christian.humer@gmail.com> |
---|---|
date | Mon, 25 Feb 2013 13:13:02 +0100 |
parents | 06a7cd6aaf00 |
children | 4958cbdbf360 |
comparison
equal
deleted
inserted
replaced
7854:8e56c6951c86 | 7855:6e4fb0ccebb1 |
---|---|
29 | 29 |
30 import javax.lang.model.element.*; | 30 import javax.lang.model.element.*; |
31 import javax.lang.model.type.*; | 31 import javax.lang.model.type.*; |
32 import javax.lang.model.util.*; | 32 import javax.lang.model.util.*; |
33 | 33 |
34 import com.oracle.truffle.api.codegen.*; | |
34 import com.oracle.truffle.codegen.processor.*; | 35 import com.oracle.truffle.codegen.processor.*; |
35 import com.oracle.truffle.codegen.processor.ast.*; | 36 import com.oracle.truffle.codegen.processor.ast.*; |
36 import com.oracle.truffle.codegen.processor.node.NodeFieldData.ExecutionKind; | 37 import com.oracle.truffle.codegen.processor.node.NodeFieldData.ExecutionKind; |
37 import com.oracle.truffle.codegen.processor.template.*; | 38 import com.oracle.truffle.codegen.processor.template.*; |
38 import com.oracle.truffle.codegen.processor.typesystem.*; | 39 import com.oracle.truffle.codegen.processor.typesystem.*; |
420 if (node.getExtensionElements() != null && !node.getExtensionElements().isEmpty()) { | 421 if (node.getExtensionElements() != null && !node.getExtensionElements().isEmpty()) { |
421 NodeGenFactory factory = new NodeGenFactory(context); | 422 NodeGenFactory factory = new NodeGenFactory(context); |
422 add(factory, node); | 423 add(factory, node); |
423 } | 424 } |
424 | 425 |
425 if (node.getSpecializations() == null) { | |
426 return; | |
427 } | |
428 | |
429 if (node.needsFactory() || childTypes.size() > 0) { | 426 if (node.needsFactory() || childTypes.size() > 0) { |
430 add(new NodeFactoryFactory(context, childTypes), node); | 427 add(new NodeFactoryFactory(context, childTypes), node); |
431 } | 428 } |
432 } | 429 } |
433 | 430 |
509 } | 506 } |
510 | 507 |
511 for (SpecializationData specialization : node.getSpecializations()) { | 508 for (SpecializationData specialization : node.getSpecializations()) { |
512 add(new SpecializedNodeFactory(context), specialization); | 509 add(new SpecializedNodeFactory(context), specialization); |
513 } | 510 } |
511 | |
512 TypeMirror nodeFactory = getContext().getEnvironment().getTypeUtils().getDeclaredType(Utils.fromTypeMirror(getContext().getType(NodeFactory.class)), node.getNodeType()); | |
513 clazz.getImplements().add(nodeFactory); | |
514 clazz.add(createCreateNodeMethod(node, createVisibility)); | |
515 clazz.add(createCreateNodeSpecializedMethod(node, createVisibility)); | |
516 clazz.add(createGetNodeClassMethod(node)); | |
517 clazz.add(createGetNodeSignaturesMethod(node)); | |
518 clazz.add(createGetInstanceMethod(node, clazz.asType(), createVisibility)); | |
519 clazz.add(createInstanceConstant(node, clazz.asType())); | |
514 } | 520 } |
515 | 521 |
516 for (NodeData childNode : childTypes.keySet()) { | 522 for (NodeData childNode : childTypes.keySet()) { |
517 if (childNode.getTemplateType().getModifiers().contains(Modifier.PRIVATE)) { | 523 if (childNode.getTemplateType().getModifiers().contains(Modifier.PRIVATE)) { |
518 continue; | 524 continue; |
529 typeModifiers.add(Modifier.STATIC); | 535 typeModifiers.add(Modifier.STATIC); |
530 typeModifiers.add(Modifier.FINAL); | 536 typeModifiers.add(Modifier.FINAL); |
531 clazz.add(type); | 537 clazz.add(type); |
532 } | 538 } |
533 } | 539 } |
540 | |
541 if (node.getParent() == null && node.getDeclaredChildren().size() > 0) { | |
542 List<NodeData> children = node.getNodeChildren(); | |
543 List<TypeMirror> types = new ArrayList<>(); | |
544 if (node.needsFactory()) { | |
545 types.add(node.getNodeType()); | |
546 } | |
547 for (NodeData child : children) { | |
548 types.add(child.getTemplateType().asType()); | |
549 } | |
550 TypeMirror commonSuperType = Utils.getCommonSuperType(getContext(), types.toArray(new TypeMirror[types.size()])); | |
551 clazz.add(createGetFactories(node, commonSuperType)); | |
552 } | |
553 | |
554 } | |
555 | |
556 private CodeExecutableElement createGetNodeClassMethod(NodeData node) { | |
557 Types types = getContext().getEnvironment().getTypeUtils(); | |
558 TypeMirror returnType = types.getDeclaredType(Utils.fromTypeMirror(getContext().getType(Class.class)), node.getNodeType()); | |
559 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeClass"); | |
560 CodeTreeBuilder builder = method.createBuilder(); | |
561 builder.startReturn().typeLiteral(node.getNodeType()).end(); | |
562 return method; | |
563 } | |
564 | |
565 private CodeExecutableElement createGetNodeSignaturesMethod(NodeData node) { | |
566 Types types = getContext().getEnvironment().getTypeUtils(); | |
567 TypeElement listType = Utils.fromTypeMirror(getContext().getType(List.class)); | |
568 TypeMirror classType = getContext().getType(Class.class); | |
569 TypeMirror returnType = types.getDeclaredType(listType, types.getDeclaredType(listType, classType)); | |
570 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC), returnType, "getNodeSignatures"); | |
571 CodeTreeBuilder builder = method.createBuilder(); | |
572 builder.startReturn(); | |
573 builder.startStaticCall(getContext().getType(Arrays.class), "asList"); | |
574 List<ExecutableElement> constructors = findUserConstructors(node); | |
575 for (ExecutableElement constructor : constructors) { | |
576 builder.startGroup(); | |
577 builder.type(getContext().getType(Arrays.class)); | |
578 builder.string(".<").type(getContext().getType(Class.class)).string(">"); | |
579 builder.startCall("asList"); | |
580 for (VariableElement param : constructor.getParameters()) { | |
581 builder.typeLiteral(param.asType()); | |
582 } | |
583 builder.end(); | |
584 builder.end(); | |
585 } | |
586 builder.end(); | |
587 builder.end(); | |
588 return method; | |
589 } | |
590 | |
591 private CodeExecutableElement createCreateNodeMethod(NodeData node, Modifier visibility) { | |
592 CodeExecutableElement method = new CodeExecutableElement(modifiers(), node.getNodeType(), "createNode"); | |
593 CodeVariableElement arguments = new CodeVariableElement(getContext().getType(Object.class), "arguments"); | |
594 method.setVarArgs(true); | |
595 method.addParameter(arguments); | |
596 | |
597 if (visibility != null) { | |
598 method.getModifiers().add(visibility); | |
599 } | |
600 | |
601 CodeTreeBuilder builder = method.createBuilder(); | |
602 List<ExecutableElement> signatures = findUserConstructors(node); | |
603 boolean ifStarted = false; | |
604 | |
605 for (ExecutableElement element : signatures) { | |
606 ifStarted = builder.startIf(ifStarted); | |
607 builder.string("arguments.length == " + element.getParameters().size()); | |
608 | |
609 int index = 0; | |
610 for (VariableElement param : element.getParameters()) { | |
611 builder.string(" && "); | |
612 if (!param.asType().getKind().isPrimitive()) { | |
613 builder.string("(arguments[" + index + "] == null || "); | |
614 } | |
615 builder.string("arguments[" + index + "] instanceof "); | |
616 builder.type(Utils.boxType(getContext(), param.asType())); | |
617 if (!param.asType().getKind().isPrimitive()) { | |
618 builder.string(")"); | |
619 } | |
620 index++; | |
621 } | |
622 builder.end(); | |
623 builder.startBlock(); | |
624 | |
625 builder.startReturn().startCall("create"); | |
626 index = 0; | |
627 for (VariableElement param : element.getParameters()) { | |
628 builder.startGroup(); | |
629 builder.string("(").type(param.asType()).string(") "); | |
630 builder.string("arguments[").string(String.valueOf(index)).string("]"); | |
631 builder.end(); | |
632 index++; | |
633 } | |
634 builder.end().end(); | |
635 | |
636 builder.end(); // block | |
637 } | |
638 | |
639 builder.startElseBlock(); | |
640 builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)); | |
641 builder.doubleQuote("Invalid create signature."); | |
642 builder.end().end(); | |
643 builder.end(); // else block | |
644 return method; | |
645 } | |
646 | |
647 private CodeExecutableElement createCreateNodeSpecializedMethod(NodeData node, Modifier visibility) { | |
648 CodeExecutableElement method = new CodeExecutableElement(modifiers(), node.getNodeType(), "createNodeSpecialized"); | |
649 CodeVariableElement nodeParam = new CodeVariableElement(node.getNodeType(), "thisNode"); | |
650 CodeVariableElement arguments = new CodeVariableElement(getContext().getType(Class.class), "types"); | |
651 method.addParameter(nodeParam); | |
652 method.addParameter(arguments); | |
653 method.setVarArgs(true); | |
654 if (visibility != null) { | |
655 method.getModifiers().add(visibility); | |
656 } | |
657 | |
658 CodeTreeBuilder builder = method.createBuilder(); | |
659 if (!node.needsRewrites(getContext())) { | |
660 builder.startThrow().startNew(getContext().getType(UnsupportedOperationException.class)).end().end(); | |
661 } else { | |
662 builder.startIf(); | |
663 builder.string("types.length == 1"); | |
664 builder.end(); | |
665 builder.startBlock(); | |
666 | |
667 builder.startReturn().startCall("createSpecialized"); | |
668 builder.string("thisNode"); | |
669 builder.string("types[0]"); | |
670 builder.end().end(); | |
671 | |
672 builder.end(); | |
673 builder.startElseBlock(); | |
674 builder.startThrow().startNew(getContext().getType(IllegalArgumentException.class)); | |
675 builder.doubleQuote("Invalid createSpecialized signature."); | |
676 builder.end().end(); | |
677 builder.end(); | |
678 } | |
679 | |
680 return method; | |
681 } | |
682 | |
683 private ExecutableElement createGetInstanceMethod(NodeData node, TypeMirror factoryType, Modifier visibility) { | |
684 CodeExecutableElement method = new CodeExecutableElement(modifiers(), factoryType, "getInstance"); | |
685 if (visibility != null) { | |
686 method.getModifiers().add(visibility); | |
687 } | |
688 method.getModifiers().add(Modifier.STATIC); | |
689 | |
690 String varName = instanceVarName(node); | |
691 | |
692 CodeTreeBuilder builder = method.createBuilder(); | |
693 builder.startIf(); | |
694 builder.string(varName).string(" == null"); | |
695 builder.end().startBlock(); | |
696 | |
697 builder.startStatement(); | |
698 builder.string(varName); | |
699 builder.string(" = "); | |
700 builder.startNew(factoryClassName(node)).end(); | |
701 builder.end(); | |
702 | |
703 builder.end(); | |
704 builder.startReturn().string(varName).end(); | |
705 return method; | |
706 } | |
707 | |
708 private String instanceVarName(NodeData node) { | |
709 if (node.getParent() != null) { | |
710 return Utils.firstLetterLowerCase(factoryClassName(node)) + "Instance"; | |
711 } else { | |
712 return "instance"; | |
713 } | |
714 } | |
715 | |
716 private CodeVariableElement createInstanceConstant(NodeData node, TypeMirror factoryType) { | |
717 String varName = instanceVarName(node); | |
718 CodeVariableElement var = new CodeVariableElement(modifiers(), factoryType, varName); | |
719 var.getModifiers().add(Modifier.PRIVATE); | |
720 var.getModifiers().add(Modifier.STATIC); | |
721 return var; | |
722 } | |
723 | |
724 private ExecutableElement createGetFactories(NodeData node, TypeMirror commonSuperType) { | |
725 Types types = getContext().getEnvironment().getTypeUtils(); | |
726 TypeMirror classType = getContext().getType(NodeFactory.class); | |
727 TypeMirror classWithWildcards = types.getDeclaredType(Utils.fromTypeMirror(classType), types.getWildcardType(commonSuperType, null)); | |
728 TypeMirror listType = types.getDeclaredType(Utils.fromTypeMirror(getContext().getType(List.class)), classWithWildcards); | |
729 | |
730 CodeExecutableElement method = new CodeExecutableElement(modifiers(PUBLIC, STATIC), listType, "getFactories"); | |
731 | |
732 CodeTreeBuilder builder = method.createBuilder(); | |
733 builder.startReturn(); | |
734 builder.startStaticCall(getContext().getType(Arrays.class), "asList"); | |
735 List<NodeData> children = node.getNodeChildren(); | |
736 if (node.needsFactory()) { | |
737 children.add(node); | |
738 } | |
739 | |
740 for (NodeData child : children) { | |
741 builder.startGroup(); | |
742 NodeData childNode = child; | |
743 List<NodeData> factories = new ArrayList<>(); | |
744 while (childNode.getParent() != null) { | |
745 factories.add(childNode); | |
746 childNode = childNode.getParent(); | |
747 } | |
748 Collections.reverse(factories); | |
749 for (NodeData nodeData : factories) { | |
750 builder.string(factoryClassName(nodeData)).string("."); | |
751 } | |
752 builder.string("getInstance()"); | |
753 builder.end(); | |
754 } | |
755 builder.end(); | |
756 builder.end(); | |
757 return method; | |
534 } | 758 } |
535 | 759 |
536 private void createFactoryMethods(NodeData node, CodeTypeElement clazz, Modifier createVisibility) { | 760 private void createFactoryMethods(NodeData node, CodeTypeElement clazz, Modifier createVisibility) { |
761 List<ExecutableElement> constructors = findUserConstructors(node); | |
762 for (ExecutableElement constructor : constructors) { | |
763 clazz.add(createCreateMethod(node, createVisibility, constructor)); | |
764 } | |
765 } | |
766 | |
767 private List<ExecutableElement> findUserConstructors(NodeData node) { | |
768 List<ExecutableElement> constructors = new ArrayList<>(); | |
537 for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(node.getNodeType()).getEnclosedElements())) { | 769 for (ExecutableElement constructor : ElementFilter.constructorsIn(Utils.fromTypeMirror(node.getNodeType()).getEnclosedElements())) { |
538 if (constructor.getModifiers().contains(PRIVATE)) { | 770 if (constructor.getModifiers().contains(PRIVATE)) { |
539 continue; | 771 continue; |
540 } | 772 } |
541 | 773 |
542 // skip node rewrite constructor | 774 // skip node rewrite constructor |
543 if (constructor.getParameters().size() == 1 && typeEquals(constructor.getParameters().get(0).asType(), node.getNodeType())) { | 775 if (constructor.getParameters().size() == 1 && typeEquals(constructor.getParameters().get(0).asType(), node.getNodeType())) { |
544 continue; | 776 continue; |
545 } | 777 } |
546 | 778 constructors.add(constructor); |
547 clazz.add(createCreateMethod(node, createVisibility, constructor)); | 779 } |
548 } | 780 return constructors; |
549 } | 781 } |
550 | 782 |
551 private CodeExecutableElement createCreateMethod(NodeData node, Modifier visibility, ExecutableElement constructor) { | 783 private CodeExecutableElement createCreateMethod(NodeData node, Modifier visibility, ExecutableElement constructor) { |
552 CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), constructor); | 784 CodeExecutableElement method = CodeExecutableElement.clone(getContext().getEnvironment(), constructor); |
553 method.setSimpleName(CodeNames.of("create")); | 785 method.setSimpleName(CodeNames.of("create")); |