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 |