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 |