comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/node/NodeCodeGenerator.java @ 12392:4e26955b6da2

Truffle-DSL: new implicit cast code generation layout supports now executeWith.
author Christian Humer <christian.humer@gmail.com>
date Thu, 03 Oct 2013 18:07:59 +0200
parents 7aa2a8c69ba3
children 8e8347ecabbc
comparison
equal deleted inserted replaced
12391:7aa2a8c69ba3 12392:4e26955b6da2
40 import com.oracle.truffle.dsl.processor.node.NodeChildData.ExecutionKind; 40 import com.oracle.truffle.dsl.processor.node.NodeChildData.ExecutionKind;
41 import com.oracle.truffle.dsl.processor.node.SpecializationGroup.TypeGuard; 41 import com.oracle.truffle.dsl.processor.node.SpecializationGroup.TypeGuard;
42 import com.oracle.truffle.dsl.processor.template.*; 42 import com.oracle.truffle.dsl.processor.template.*;
43 import com.oracle.truffle.dsl.processor.template.TemplateMethod.Signature; 43 import com.oracle.truffle.dsl.processor.template.TemplateMethod.Signature;
44 import com.oracle.truffle.dsl.processor.typesystem.*; 44 import com.oracle.truffle.dsl.processor.typesystem.*;
45 import com.sun.org.apache.xml.internal.dtm.ref.DTMDefaultBaseIterators.*;
46 45
47 public class NodeCodeGenerator extends CompilationUnitFactory<NodeData> { 46 public class NodeCodeGenerator extends CompilationUnitFactory<NodeData> {
48 47
49 private static final String THIS_NODE_LOCAL_VAR_NAME = "thisNode"; 48 private static final String THIS_NODE_LOCAL_VAR_NAME = "thisNode";
50 49
952 } 951 }
953 clazz.add(createCachedExecute(node, polymorph, genericCachedExecute)); 952 clazz.add(createCachedExecute(node, polymorph, genericCachedExecute));
954 } 953 }
955 } 954 }
956 955
957 for (CodeExecutableElement method : createImplicitChildrenAccessors(node, clazz)) { 956 for (CodeExecutableElement method : createImplicitChildrenAccessors()) {
958 clazz.add(method); 957 clazz.add(method);
959 } 958 }
960 959
961 clazz.add(createGenericExecuteAndSpecialize(node, rootGroup)); 960 clazz.add(createGenericExecuteAndSpecialize(node, rootGroup));
962 clazz.add(createInfoMessage(node)); 961 clazz.add(createInfoMessage(node));
965 if (node.getGenericSpecialization() != null && node.getGenericSpecialization().isReachable()) { 964 if (node.getGenericSpecialization() != null && node.getGenericSpecialization().isReachable()) {
966 clazz.add(createGenericExecute(node, rootGroup)); 965 clazz.add(createGenericExecute(node, rootGroup));
967 } 966 }
968 } 967 }
969 968
970 private List<CodeExecutableElement> createImplicitChildrenAccessors(NodeData node, CodeTypeElement clazz) { 969 private List<CodeExecutableElement> createImplicitChildrenAccessors() {
970 NodeData node = getModel().getNode();
971 List<CodeExecutableElement> methods = new ArrayList<>(); 971 List<CodeExecutableElement> methods = new ArrayList<>();
972 Map<NodeChildData, Set<TypeData>> expectTypes = new HashMap<>(); 972 Map<NodeChildData, Set<TypeData>> expectTypes = new HashMap<>();
973 for (ExecutableTypeData executableType : node.getExecutableTypes()) { 973 for (ExecutableTypeData executableType : node.getExecutableTypes()) {
974 for (int i = 0; i < executableType.getEvaluatedCount(); i++) { 974 for (int i = 0; i < executableType.getEvaluatedCount(); i++) {
975 ActualParameter parameter = executableType.getSignatureParameter(i); 975 ActualParameter parameter = executableType.getSignatureParameter(i);
2016 2016
2017 builder.string(typeName(param)); 2017 builder.string(typeName(param));
2018 2018
2019 builder.end(); 2019 builder.end();
2020 } else { 2020 } else {
2021 List<TypeData> sourceTypes = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
2021 TypeData expectType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null; 2022 TypeData expectType = sourceParameter != null ? sourceParameter.getTypeSystemType() : null;
2022 builder.tree(createExecuteExpression(parent, child, expectType, targetExecutable, param, unexpectedParameter, null)); 2023 if (sourceTypes.size() > 1) {
2024 builder.tree(createExecuteExpressions(parent, param, expectType));
2025 } else {
2026 builder.tree(createExecuteExpression(parent, child, expectType, targetExecutable, param, unexpectedParameter, null));
2027 }
2023 } 2028 }
2024 return builder.getRoot(); 2029 return builder.getRoot();
2025 } 2030 }
2026 2031
2027 private String createExecuteChildMethodName(ActualParameter param, boolean expect) { 2032 private String createExecuteChildMethodName(ActualParameter param, boolean expect) {
2028 NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName()); 2033 NodeChildData child = getModel().getNode().findChild(param.getSpecification().getName());
2034 if (child.getExecuteWith().size() > 0) {
2035 return null;
2036 }
2029 List<TypeData> sourceTypes = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); 2037 List<TypeData> sourceTypes = child.getNodeData().getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
2030 if (sourceTypes.size() <= 1) { 2038 if (sourceTypes.size() <= 1) {
2031 return null; 2039 return null;
2032 } 2040 }
2033 String prefix = expect ? "expect" : "execute"; 2041 String prefix = expect ? "expect" : "execute";
2055 String childExecuteName = createExecuteChildMethodName(param, expectType != null); 2063 String childExecuteName = createExecuteChildMethodName(param, expectType != null);
2056 if (childExecuteName == null) { 2064 if (childExecuteName == null) {
2057 return null; 2065 return null;
2058 } 2066 }
2059 2067
2068 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, expectType != null ? STATIC : FINAL), param.getType(), childExecuteName);
2069 method.getThrownTypes().add(getContext().getTruffleTypes().getUnexpectedValueException());
2070 method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue"));
2071 if (expectType != null) {
2072 method.addParameter(new CodeVariableElement(expectType.getPrimitiveType(), valueNameEvaluated(param)));
2073 }
2074 method.addParameter(new CodeVariableElement(getContext().getType(Class.class), typeName(param)));
2075
2076 CodeTreeBuilder builder = method.createBuilder();
2077 builder.declaration(param.getType(), valueName(param));
2078 builder.tree(createExecuteExpressions(builder, param, expectType));
2079 builder.startReturn().string(valueName(param)).end();
2080
2081 return method;
2082 }
2083
2084 private CodeTree createExecuteExpressions(CodeTreeBuilder parent, ActualParameter param, TypeData expectType) {
2085 CodeTreeBuilder builder = parent.create();
2060 NodeData node = getModel().getNode(); 2086 NodeData node = getModel().getNode();
2061 NodeChildData child = node.findChild(param.getSpecification().getName()); 2087 NodeChildData child = node.findChild(param.getSpecification().getName());
2062 List<TypeData> sourceTypes = node.getTypeSystem().lookupSourceTypes(param.getTypeSystemType()); 2088 List<TypeData> sourceTypes = node.getTypeSystem().lookupSourceTypes(param.getTypeSystemType());
2063 assert sourceTypes.size() >= 1;
2064
2065 CodeExecutableElement method = new CodeExecutableElement(modifiers(PROTECTED, expectType != null ? STATIC : FINAL), param.getType(), childExecuteName);
2066
2067 method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frameValue"));
2068 if (expectType != null) {
2069 method.addParameter(new CodeVariableElement(expectType.getPrimitiveType(), valueNameEvaluated(param)));
2070 }
2071 method.addParameter(new CodeVariableElement(getContext().getType(Class.class), typeName(param)));
2072 CodeTreeBuilder builder = method.createBuilder();
2073
2074 builder.declaration(param.getType(), valueName(param));
2075
2076 boolean unexpected = false;
2077 boolean elseIf = false; 2089 boolean elseIf = false;
2078 int index = 0; 2090 int index = 0;
2079 for (TypeData typeData : sourceTypes) { 2091 for (TypeData sourceType : sourceTypes) {
2080 if (index < sourceTypes.size() - 1) { 2092 if (index < sourceTypes.size() - 1) {
2081 elseIf = builder.startIf(elseIf); 2093 elseIf = builder.startIf(elseIf);
2082 builder.string(typeName(param)).string(" == ").typeLiteral(typeData.getPrimitiveType()); 2094 builder.string(typeName(param)).string(" == ").typeLiteral(sourceType.getPrimitiveType());
2083 builder.end(); 2095 builder.end();
2084 builder.startBlock(); 2096 builder.startBlock();
2085 } else { 2097 } else {
2086 builder.startElseBlock(); 2098 builder.startElseBlock();
2087 } 2099 }
2088 2100
2089 ExecutableTypeData implictExecutableTypeData = child.getNodeData().findExecutableType(typeData, child.getExecuteWith().size()); 2101 ExecutableTypeData implictExecutableTypeData = child.getNodeData().findExecutableType(sourceType, child.getExecuteWith().size());
2090 if (!unexpected && implictExecutableTypeData.hasUnexpectedValue(getContext())) { 2102 if (implictExecutableTypeData == null) {
2091 unexpected = true; 2103 /*
2092 } 2104 * For children with executeWith.size() > 0 an executable type may not exist so
2093 ImplicitCastData cast = child.getNodeData().getTypeSystem().lookupCast(typeData, param.getTypeSystemType()); 2105 * use the generic executable type which is guaranteed to exist. An expect call
2106 * is inserted automatically by #createExecuteExpression.
2107 */
2108 implictExecutableTypeData = child.getNodeData().findExecutableType(node.getTypeSystem().getGenericTypeData(), child.getExecuteWith().size());
2109 }
2110
2111 ImplicitCastData cast = child.getNodeData().getTypeSystem().lookupCast(sourceType, param.getTypeSystemType());
2094 CodeTree execute = createExecuteExpression(builder, child, expectType, implictExecutableTypeData, param, null, cast); 2112 CodeTree execute = createExecuteExpression(builder, child, expectType, implictExecutableTypeData, param, null, cast);
2095 builder.statement(execute); 2113 builder.statement(execute);
2096 builder.end(); 2114 builder.end();
2097 index++; 2115 index++;
2098 } 2116 }
2099 2117 return builder.getRoot();
2100 builder.startReturn().string(valueName(param)).end();
2101
2102 if (unexpected) {
2103 method.getThrownTypes().add(getContext().getTruffleTypes().getUnexpectedValueException());
2104 }
2105
2106 return method;
2107 } 2118 }
2108 2119
2109 private CodeTree createExecuteExpression(CodeTreeBuilder parent, NodeChildData child, TypeData expectType, ExecutableTypeData targetExecutable, ActualParameter targetParameter, 2120 private CodeTree createExecuteExpression(CodeTreeBuilder parent, NodeChildData child, TypeData expectType, ExecutableTypeData targetExecutable, ActualParameter targetParameter,
2110 ActualParameter unexpectedParameter, ImplicitCastData cast) { 2121 ActualParameter unexpectedParameter, ImplicitCastData cast) {
2111 CodeTreeBuilder builder = parent.create(); 2122 CodeTreeBuilder builder = parent.create();
2113 builder.string(" = "); 2124 builder.string(" = ");
2114 if (cast != null) { 2125 if (cast != null) {
2115 startCallTypeSystemMethod(getContext(), builder, child.getNodeData(), cast.getMethodName()); 2126 startCallTypeSystemMethod(getContext(), builder, child.getNodeData(), cast.getMethodName());
2116 } 2127 }
2117 2128
2118 if (targetExecutable.getType().needsCastTo(context, targetParameter.getTypeSystemType()) && cast == null) { 2129 TypeData expectTarget = targetParameter.getTypeSystemType();
2119 startCallTypeSystemMethod(getContext(), builder, child.getNodeData(), TypeSystemCodeGenerator.expectTypeMethodName(targetParameter.getTypeSystemType())); 2130 if (cast != null) {
2131 expectTarget = cast.getSourceType();
2132 }
2133
2134 if (targetExecutable.getType().needsCastTo(context, expectTarget)) {
2135 startCallTypeSystemMethod(getContext(), builder, child.getNodeData(), TypeSystemCodeGenerator.expectTypeMethodName(expectTarget));
2120 } 2136 }
2121 2137
2122 NodeData node = getModel().getNode(); 2138 NodeData node = getModel().getNode();
2123 if (expectType == null) { 2139 if (expectType == null) {
2124 builder.tree(createExecuteChildExpression(builder, child, targetParameter, targetExecutable, unexpectedParameter)); 2140 builder.tree(createExecuteChildExpression(builder, child, targetParameter, targetExecutable, unexpectedParameter));