Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 part of ir; | |
|
kasperl
2013/11/06 08:30:04
Add copyright header.
I'd make the IrBuilder live
lukas
2013/11/06 11:36:08
Done.
| |
| 2 | |
| 3 class IrBuilderTask extends CompilerTask { | |
| 4 final Map<Element, INode> iNodes = new Map<Element, INode>(); | |
| 5 | |
| 6 IrBuilderTask(Compiler compiler) : super(compiler); | |
| 7 | |
| 8 String get name => 'IR builder'; | |
| 9 | |
| 10 void buildNodes() { | |
| 11 Map<Element, TreeElements> resolved = | |
| 12 compiler.enqueuer.resolution.resolvedElements; | |
| 13 resolved.forEach((Element element, TreeElements elementsMapping) { | |
| 14 element = element.implementation; | |
| 15 | |
| 16 // @lry debug | |
| 17 if (element.name == 'noInline') | |
| 18 print(0); | |
| 19 | |
| 20 SourceFile sourceFile = elementSourceFile(element); | |
| 21 INodeBuilderVisitor visitor = | |
| 22 new INodeBuilderVisitor(elementsMapping, compiler, sourceFile); | |
| 23 INode iNode; | |
| 24 ElementKind kind = element.kind; | |
| 25 if (kind == ElementKind.GENERATIVE_CONSTRUCTOR) { | |
| 26 // iNode = compileConstructor(builder, work); | |
| 27 } else if (kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY || | |
| 28 kind == ElementKind.FUNCTION || | |
| 29 kind == ElementKind.GETTER || | |
| 30 kind == ElementKind.SETTER) { | |
| 31 iNode = visitor.buildMethod(element); | |
| 32 } else if (kind == ElementKind.FIELD) { | |
| 33 // @lry the below assertion holds in the ssa-builder, but not here. | |
| 34 // are instance fields never enqueued in the backend? | |
| 35 // compare to inferrer, which is not worklist-based but runs over all | |
| 36 // resolved elements | |
| 37 // assert(!element.isInstanceMember()); | |
| 38 // iNode = builder.buildLazyInitializer(element); | |
| 39 } else { | |
| 40 compiler.internalErrorOnElement(element, | |
| 41 'unexpected element kind $kind'); | |
| 42 } | |
| 43 | |
| 44 if (iNode != null) { | |
| 45 iNodes[element] = iNode; | |
| 46 } | |
| 47 | |
| 48 // @lry debug | |
| 49 if (element.name == 'noInline') { | |
| 50 (element as dynamic).beginToken.next = null; | |
| 51 (element as dynamic).cachedNode = null; | |
| 52 print(iNode); | |
| 53 } | |
| 54 | |
| 55 }); | |
| 56 } | |
| 57 | |
| 58 SourceFile elementSourceFile(Element element) { | |
| 59 if (element is FunctionElement) { | |
| 60 FunctionElement functionElement = element; | |
| 61 if (functionElement.patch != null) element = functionElement.patch; | |
| 62 } | |
| 63 return element.getCompilationUnit().script.file; | |
| 64 } | |
| 65 } | |
| 66 | |
| 67 | |
| 68 class INodeBuilderVisitor extends ResolvedVisitor<INode> { | |
| 69 SourceFile sourceFile; | |
| 70 | |
| 71 Context context; | |
| 72 | |
| 73 INodeBuilderVisitor(TreeElements elements, Compiler compiler, | |
| 74 this.sourceFile) : super(elements, compiler) { | |
| 75 context = new Context(this); | |
| 76 } | |
| 77 | |
| 78 INode buildMethod(FunctionElement functionElement) { | |
| 79 assert(invariant(functionElement, functionElement.isImplementation)); | |
| 80 FunctionExpression function = functionElement.parseNode(compiler); | |
| 81 assert(function != null); | |
| 82 assert(!function.modifiers.isExternal()); | |
| 83 assert(elements[function] != null); | |
| 84 return buildNode(function); | |
| 85 } | |
| 86 | |
| 87 INode buildNode(Node node) { | |
| 88 try { | |
| 89 return node.accept(this); | |
| 90 } catch(e) { | |
| 91 if (e == ABORT_INODE_BUILDER) return null; | |
| 92 throw e; | |
| 93 } | |
| 94 } | |
| 95 | |
| 96 ConstantSystem get constantSystem => compiler.backend.constantSystem; | |
| 97 | |
| 98 Position nodePos(Node node) { | |
| 99 return new Position(sourceFile, node.getBeginToken().charOffset); | |
| 100 } | |
| 101 | |
| 102 INode visitFunctionExpression(FunctionExpression node) { | |
| 103 IFunction result = new IFunction(nodePos(node), const<INode>[]); | |
|
ngeoffray
2013/11/05 12:58:35
Should we create that at the end of the visit, onc
lukas
2013/11/05 17:10:50
It's done here for now because the "IrReturn" poin
| |
| 104 context.openFunction(result); | |
| 105 INode body = node.body.accept(this); | |
| 106 if (context.statements.isNotEmpty) { | |
| 107 result.statements = | |
| 108 <INode>[]..addAll(context.constants)..addAll(context.statements); | |
| 109 } | |
| 110 context.closeFunction(); | |
| 111 if (!context.isTopLevel()) { | |
| 112 context.enterStatement(result); | |
| 113 } | |
| 114 return result; | |
| 115 } | |
| 116 | |
| 117 INode visitBlock(Block node) { | |
| 118 for (Node n in node.statements.nodes) { | |
| 119 n.accept(this); | |
| 120 } | |
| 121 return new NoValue(); | |
| 122 } | |
| 123 | |
| 124 INode visitReturn(Return node) { | |
| 125 INode value = node.expression.accept(this); | |
| 126 return context.enterStatement( | |
| 127 new IReturn(nodePos(node), context.returnFunction, value)); | |
| 128 } | |
| 129 | |
| 130 IConstant visitLiteralBool(LiteralBool node) => | |
| 131 context.enterConstant(constantSystem.createBool(node.value), node); | |
| 132 | |
| 133 IConstant visitLiteralDouble(LiteralDouble node) => | |
| 134 context.enterConstant(constantSystem.createDouble(node.value), node); | |
| 135 | |
| 136 IConstant visitLiteralInt(LiteralInt node) => | |
| 137 context.enterConstant(constantSystem.createInt(node.value), node); | |
| 138 | |
| 139 IConstant visitLiteralString(LiteralString node) => | |
| 140 context.enterConstant( | |
| 141 constantSystem.createString(node.dartString, node), node); | |
| 142 | |
| 143 IConstant visitLiteralNull(LiteralNull node) => | |
| 144 context.enterConstant(constantSystem.createNull(), node); | |
| 145 | |
| 146 // INode visitLiteralList(LiteralList node) => visitExpression(node); | |
| 147 // INode visitLiteralMap(LiteralMap node) => visitExpression(node); | |
| 148 // INode visitLiteralMapEntry(LiteralMapEntry node) => visitNode(node); | |
| 149 // INode visitLiteralSymbol(LiteralSymbol node) => visitExpression(node); | |
| 150 | |
| 151 | |
| 152 INode visitAssert(Send node) { | |
| 153 return giveup(); | |
| 154 } | |
| 155 | |
| 156 INode visitClosureSend(Send node) { | |
| 157 return giveup(); | |
| 158 } | |
| 159 | |
| 160 INode visitDynamicSend(Send node) { | |
| 161 return giveup(); | |
| 162 } | |
| 163 | |
| 164 INode visitGetterSend(Send node) { | |
| 165 return giveup(); | |
| 166 } | |
| 167 | |
| 168 INode visitOperatorSend(Send node) { | |
| 169 return giveup(); | |
| 170 } | |
| 171 | |
| 172 INode visitStaticSend(Send node) { | |
| 173 return giveup(); | |
| 174 } | |
| 175 | |
| 176 INode visitSuperSend(Send node) { | |
| 177 return giveup(); | |
| 178 } | |
| 179 | |
| 180 INode visitTypeReferenceSend(Send node) { | |
| 181 return giveup(); | |
| 182 } | |
| 183 | |
| 184 static final String ABORT_INODE_BUILDER = "INode builder aborted"; | |
| 185 | |
| 186 INode giveup() => throw ABORT_INODE_BUILDER; | |
| 187 | |
| 188 void internalError(String reason, {Node node}) { | |
| 189 giveup(); | |
| 190 } | |
| 191 } | |
| 192 | |
| 193 class Context { | |
| 194 INodeBuilderVisitor visitor; | |
| 195 Context(this.visitor); | |
| 196 | |
| 197 List<IFunction> returnFunctionList = <IFunction>[]; | |
| 198 IFunction get returnFunction => returnFunctionList.last; | |
|
ngeoffray
2013/11/05 12:58:35
Are you anticipating inlining?
lukas
2013/11/05 17:10:50
Yes - again, depends on the IR we use.
| |
| 199 | |
| 200 List<List<INode>> statementsList = <List<INode>>[]; | |
| 201 List<INode> get statements => statementsList.last; | |
| 202 | |
| 203 List<List<IConstant>> constantsList = <List<IConstant>>[]; | |
|
ngeoffray
2013/11/05 12:58:35
I think we'll just have one giant list/set of cons
lukas
2013/11/05 17:10:50
We have one list per function here. The reason it'
| |
| 204 List<IConstant> get constants => constantsList.last; | |
| 205 | |
| 206 IConstant enterConstant(Constant value, Node node) { | |
| 207 return constants.firstWhere((c) => c.value == value, orElse: () { | |
| 208 IConstant c = new IConstant(visitor.nodePos(node), value); | |
| 209 constants.add(c); | |
| 210 return c; | |
| 211 }); | |
| 212 } | |
| 213 | |
| 214 INode enterStatement(INode statement) { | |
| 215 statements.add(statement); | |
| 216 return statement; | |
| 217 } | |
| 218 | |
| 219 void openFunction(IFunction function) { | |
| 220 returnFunctionList.add(function); | |
| 221 statementsList.add(<INode>[]); | |
| 222 constantsList.add(<IConstant>[]); | |
| 223 } | |
| 224 | |
| 225 void closeFunction() { | |
| 226 returnFunctionList.removeLast(); | |
| 227 statementsList.removeLast(); | |
| 228 constantsList.removeLast(); | |
| 229 } | |
| 230 | |
| 231 void openContinuation() { | |
| 232 statementsList.add(<INode>[]); | |
| 233 } | |
| 234 | |
| 235 void closeContinuation() { | |
| 236 statementsList.removeLast(); | |
| 237 } | |
| 238 | |
| 239 isTopLevel() => returnFunctionList.isEmpty; | |
| 240 } | |
| OLD | NEW |