Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 library ir_builder; | |
| 6 | |
| 7 import 'ir_nodes.dart'; | |
| 8 import '../elements/elements.dart'; | |
| 9 import '../dart2jslib.dart'; | |
| 10 import '../source_file.dart'; | |
| 11 import '../tree/tree.dart'; | |
| 12 | |
| 13 class IrBuilderTask extends CompilerTask { | |
| 14 final Map<Element, IrNode> irNodes = new Map<Element, IrNode>(); | |
|
karlklose
2013/11/06 09:11:28
How about calling this field 'nodes'?
lukas
2013/11/06 11:36:08
Done.
| |
| 15 | |
| 16 IrBuilderTask(Compiler compiler) : super(compiler); | |
| 17 | |
| 18 String get name => 'IR builder'; | |
| 19 | |
| 20 void buildNodes() { | |
| 21 Map<Element, TreeElements> resolved = | |
| 22 compiler.enqueuer.resolution.resolvedElements; | |
| 23 resolved.forEach((Element element, TreeElements elementsMapping) { | |
| 24 element = element.implementation; | |
| 25 | |
| 26 // @lry debug | |
| 27 if (element.name == 'noInline') | |
| 28 print(0); | |
| 29 | |
| 30 SourceFile sourceFile = elementSourceFile(element); | |
| 31 IrNodeBuilderVisitor visitor = | |
| 32 new IrNodeBuilderVisitor(elementsMapping, compiler, sourceFile); | |
| 33 IrNode irNode; | |
| 34 ElementKind kind = element.kind; | |
| 35 if (kind == ElementKind.GENERATIVE_CONSTRUCTOR) { | |
| 36 // irNode = compileConstructor(builder, work); | |
| 37 } else if (kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY || | |
| 38 kind == ElementKind.FUNCTION || | |
| 39 kind == ElementKind.GETTER || | |
| 40 kind == ElementKind.SETTER) { | |
| 41 irNode = visitor.buildMethod(element); | |
| 42 } else if (kind == ElementKind.FIELD) { | |
| 43 // @lry the below assertion holds in the ssa-builder, but not here. | |
| 44 // are instance fields never enqueued in the backend? | |
| 45 // compare to inferrer, which is not worklist-based but runs over all | |
| 46 // resolved elements | |
| 47 // assert(!element.isInstanceMember()); | |
| 48 // irNode = builder.buildLazyInitializer(element); | |
| 49 } else { | |
| 50 compiler.internalErrorOnElement(element, | |
| 51 'unexpected element kind $kind'); | |
| 52 } | |
| 53 | |
| 54 if (irNode != null) { | |
| 55 irNodes[element] = irNode; | |
| 56 } | |
| 57 | |
| 58 // @lry debug | |
| 59 if (element.name == 'noInline') { | |
| 60 // (element as dynamic).beginToken.next = null; | |
| 61 // (element as dynamic).cachedNode = null; | |
| 62 print(irNode); | |
| 63 } | |
| 64 | |
| 65 }); | |
| 66 } | |
| 67 | |
| 68 SourceFile elementSourceFile(Element element) { | |
| 69 if (element is FunctionElement) { | |
| 70 FunctionElement functionElement = element; | |
| 71 if (functionElement.patch != null) element = functionElement.patch; | |
| 72 } | |
| 73 return element.getCompilationUnit().script.file; | |
| 74 } | |
| 75 } | |
| 76 | |
| 77 | |
| 78 class IrNodeBuilderVisitor extends ResolvedVisitor<IrNode> { | |
| 79 SourceFile sourceFile; | |
| 80 | |
| 81 Context context; | |
| 82 | |
| 83 IrNodeBuilderVisitor(TreeElements elements, Compiler compiler, | |
| 84 this.sourceFile) : super(elements, compiler) { | |
| 85 context = new Context(this); | |
| 86 } | |
| 87 | |
| 88 IrNode buildMethod(FunctionElement functionElement) { | |
| 89 assert(invariant(functionElement, functionElement.isImplementation)); | |
| 90 FunctionExpression function = functionElement.parseNode(compiler); | |
| 91 assert(function != null); | |
| 92 assert(!function.modifiers.isExternal()); | |
| 93 assert(elements[function] != null); | |
| 94 return buildNode(function); | |
| 95 } | |
| 96 | |
| 97 IrNode buildNode(Node node) { | |
| 98 try { | |
| 99 return node.accept(this); | |
| 100 } catch(e) { | |
| 101 if (e == ABORT_IRNODE_BUILDER) return null; | |
| 102 throw e; | |
| 103 } | |
| 104 } | |
| 105 | |
| 106 ConstantSystem get constantSystem => compiler.backend.constantSystem; | |
| 107 | |
| 108 int nodeOffset(Node node) { | |
| 109 return node.getBeginToken().charOffset; | |
| 110 } | |
| 111 | |
| 112 IrNode visitFunctionExpression(FunctionExpression node) { | |
| 113 IrFunction result = new IrFunction(nodeOffset(node), const<IrNode>[]); | |
|
karlklose
2013/11/06 09:11:28
Initialize with <IrNode>[] (growable list) and fil
lukas
2013/11/06 11:36:08
Done.
| |
| 114 context.openFunction(result); | |
| 115 IrNode body = node.body.accept(this); | |
| 116 if (context.statements.isNotEmpty) { | |
| 117 result.statements = | |
| 118 <IrNode>[]..addAll(context.constants)..addAll(context.statements); | |
| 119 } | |
| 120 context.closeFunction(); | |
| 121 if (!context.isTopLevel()) { | |
| 122 context.enterStatement(result); | |
| 123 } | |
| 124 return result; | |
| 125 } | |
| 126 | |
| 127 IrNode visitBlock(Block node) { | |
| 128 for (Node n in node.statements.nodes) { | |
| 129 n.accept(this); | |
| 130 } | |
| 131 return const IrNoValue(); | |
| 132 } | |
| 133 | |
| 134 IrNode visitReturn(Return node) { | |
| 135 IrNode value; | |
| 136 if (node.expression == null) { | |
| 137 value = context.enterConstant(constantSystem.createNull(), node); | |
| 138 } else { | |
| 139 value = node.expression.accept(this); | |
| 140 } | |
| 141 return context.enterStatement( | |
| 142 new IrReturn(nodeOffset(node), context.returnFunction, value)); | |
| 143 } | |
| 144 | |
| 145 IrConstant visitLiteralBool(LiteralBool node) => | |
| 146 context.enterConstant(constantSystem.createBool(node.value), node); | |
| 147 | |
| 148 IrConstant visitLiteralDouble(LiteralDouble node) => | |
| 149 context.enterConstant(constantSystem.createDouble(node.value), node); | |
| 150 | |
| 151 IrConstant visitLiteralInt(LiteralInt node) => | |
| 152 context.enterConstant(constantSystem.createInt(node.value), node); | |
| 153 | |
| 154 IrConstant visitLiteralString(LiteralString node) => | |
| 155 context.enterConstant( | |
| 156 constantSystem.createString(node.dartString, node), node); | |
| 157 | |
| 158 IrConstant visitLiteralNull(LiteralNull node) => | |
| 159 context.enterConstant(constantSystem.createNull(), node); | |
| 160 | |
| 161 // IrNode visitLiteralList(LiteralList node) => visitExpression(node); | |
| 162 // IrNode visitLiteralMap(LiteralMap node) => visitExpression(node); | |
| 163 // IrNode visitLiteralMapEntry(LiteralMapEntry node) => visitNode(node); | |
| 164 // IrNode visitLiteralSymbol(LiteralSymbol node) => visitExpression(node); | |
| 165 | |
| 166 | |
| 167 IrNode visitAssert(Send node) { | |
| 168 return giveup(); | |
| 169 } | |
| 170 | |
| 171 IrNode visitClosureSend(Send node) { | |
| 172 return giveup(); | |
| 173 } | |
| 174 | |
| 175 IrNode visitDynamicSend(Send node) { | |
| 176 return giveup(); | |
| 177 } | |
| 178 | |
| 179 IrNode visitGetterSend(Send node) { | |
| 180 return giveup(); | |
| 181 } | |
| 182 | |
| 183 IrNode visitOperatorSend(Send node) { | |
| 184 return giveup(); | |
| 185 } | |
| 186 | |
| 187 IrNode visitStaticSend(Send node) { | |
| 188 return giveup(); | |
| 189 } | |
| 190 | |
| 191 IrNode visitSuperSend(Send node) { | |
| 192 return giveup(); | |
| 193 } | |
| 194 | |
| 195 IrNode visitTypeReferenceSend(Send node) { | |
| 196 return giveup(); | |
| 197 } | |
| 198 | |
| 199 static final String ABORT_IRNODE_BUILDER = "IrNode builder aborted"; | |
| 200 | |
| 201 IrNode giveup() => throw ABORT_IRNODE_BUILDER; | |
| 202 | |
| 203 void internalError(String reason, {Node node}) { | |
| 204 giveup(); | |
| 205 } | |
| 206 } | |
| 207 | |
| 208 class Context { | |
| 209 IrNodeBuilderVisitor visitor; | |
| 210 Context(this.visitor); | |
| 211 | |
| 212 List<IrFunction> returnFunctionList = <IrFunction>[]; | |
| 213 IrFunction get returnFunction => returnFunctionList.last; | |
| 214 | |
| 215 List<List<IrNode>> statementsList = <List<IrNode>>[]; | |
| 216 List<IrNode> get statements => statementsList.last; | |
| 217 | |
| 218 List<List<IrConstant>> constantsList = <List<IrConstant>>[]; | |
| 219 List<IrConstant> get constants => constantsList.last; | |
| 220 | |
| 221 IrConstant enterConstant(Constant value, Node node) { | |
| 222 return constants.firstWhere((c) => c.value == value, orElse: () { | |
| 223 IrConstant c = new IrConstant(visitor.nodeOffset(node), value); | |
| 224 constants.add(c); | |
| 225 return c; | |
| 226 }); | |
| 227 } | |
| 228 | |
| 229 IrNode enterStatement(IrNode statement) { | |
| 230 statements.add(statement); | |
| 231 return statement; | |
| 232 } | |
| 233 | |
| 234 void openFunction(IrFunction function) { | |
| 235 returnFunctionList.add(function); | |
| 236 statementsList.add(<IrNode>[]); | |
| 237 constantsList.add(<IrConstant>[]); | |
| 238 } | |
| 239 | |
| 240 void closeFunction() { | |
| 241 returnFunctionList.removeLast(); | |
| 242 statementsList.removeLast(); | |
| 243 constantsList.removeLast(); | |
| 244 } | |
| 245 | |
| 246 void openContinuation() { | |
| 247 statementsList.add(<IrNode>[]); | |
| 248 } | |
| 249 | |
| 250 void closeContinuation() { | |
| 251 statementsList.removeLast(); | |
| 252 } | |
| 253 | |
| 254 isTopLevel() => returnFunctionList.isEmpty; | |
| 255 } | |
| OLD | NEW |