Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: sdk/lib/_internal/compiler/implementation/ir/ir_builder.dart

Issue 57873002: Build new IR for functions returning a constant (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: no nested functions in ir Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(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.
ngeoffray 2013/11/21 15:02:05 Please add high-level comments on classes in this
lukas 2013/11/21 17:14:27 Done.
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 import '../scanner/scannerlib.dart' show Token;
13 import '../js_backend/js_backend.dart' show JavaScriptBackend;
14
15 class IrBuilderTask extends CompilerTask {
16 final Map<Element, IrNode> nodes = new Map<Element, IrNode>();
17
18 IrBuilderTask(Compiler compiler) : super(compiler);
19
20 String get name => 'IR builder';
21
22 void buildNodes() {
23 // TODO(lry): support checked-mode checks.
24 if (compiler.enableTypeAssertions) return;
25
26 Map<Element, TreeElements> resolved =
27 compiler.enqueuer.resolution.resolvedElements;
28 resolved.forEach((Element element, TreeElements elementsMapping) {
29 element = element.implementation;
30
31 SourceFile sourceFile = elementSourceFile(element);
32 IrNodeBuilderVisitor visitor =
33 new IrNodeBuilderVisitor(elementsMapping, compiler, sourceFile);
34 IrNode irNode;
35 ElementKind kind = element.kind;
36 if (kind == ElementKind.GENERATIVE_CONSTRUCTOR) {
37 // TODO(lry): build ir for constructors.
38 } else if (kind == ElementKind.GENERATIVE_CONSTRUCTOR_BODY ||
39 kind == ElementKind.FUNCTION ||
40 kind == ElementKind.GETTER ||
41 kind == ElementKind.SETTER) {
42 irNode = visitor.buildMethod(element);
43 } else if (kind == ElementKind.FIELD) {
44 // TODO(lry): build ir for lazy initializers of static fields.
45 } else {
46 compiler.internalErrorOnElement(element,
47 'unexpected element kind $kind');
48 }
49
50 if (irNode != null) {
51 nodes[element] = irNode;
52 unlinkTreeAndToken(element);
53 }
54 });
55 }
56
57 void unlinkTreeAndToken(element) {
58 // TODO(lry): Make the dart backend generate code from IR nodes.
59 if (compiler.backend is JavaScriptBackend) {
60 element.beginToken.next = null;
61 element.cachedNode = null;
62 }
63 }
64
65 SourceFile elementSourceFile(Element element) {
66 if (element is FunctionElement) {
67 FunctionElement functionElement = element;
68 if (functionElement.patch != null) element = functionElement.patch;
69 }
70 return element.getCompilationUnit().script.file;
71 }
72 }
73
74
75 class IrNodeBuilderVisitor extends ResolvedVisitor<IrNode> {
76 final SourceFile sourceFile;
77
78 IrNodeBuilderVisitor(
79 TreeElements elements,
80 Compiler compiler,
81 this.sourceFile)
82 : super(elements, compiler);
83
84 IrBuilder builder;
85
86 IrNode buildMethod(FunctionElement functionElement) {
87 return nullIfGiveup(() => buildMethodInternal(functionElement));
88 }
89
90 IrNode buildMethodInternal(FunctionElement functionElement) {
91 assert(invariant(functionElement, functionElement.isImplementation));
92 FunctionExpression function = functionElement.parseNode(compiler);
93 assert(function != null);
94 assert(!function.modifiers.isExternal());
95 assert(elements[function] != null);
96
97 int endPosition = function.getEndToken().charOffset;
98 int namePosition = elements[function].position().charOffset;
99 IrFunction result = new IrFunction(
100 nodePosition(function), endPosition, namePosition, <IrNode>[]);
101 builder = new IrBuilder(this);
102 builder.enterBlock();
103 if (function.hasBody()) {
104 function.body.accept(this);
105 ensureReturn(function);
106 result.statements
107 ..addAll(builder.constants.values)
108 ..addAll(builder.statements);
109 }
110 builder.exitBlock();
111 return result;
112 }
113
114 IrNode buildNode(Node node) {
ngeoffray 2013/11/21 15:02:05 Unused.
lukas 2013/11/21 17:14:27 Done.
115 }
116
117 ConstantSystem get constantSystem => compiler.backend.constantSystem;
118
119 /* int | PositionWithIdentifierName */ nodePosition(Node node) {
120 Token token = node.getBeginToken();
121 if (token.isIdentifier()) {
122 return new PositionWithIdentifierName(token.charOffset, token.value);
123 } else {
124 return token.charOffset;
125 }
126 }
127
128 void ensureReturn(FunctionExpression node) {
129 if (!builder.returnOnAllBranches) {
ngeoffray 2013/11/21 15:02:05 Nit: Reverse the condition and return to avoid ind
lukas 2013/11/21 17:14:27 Done.
130 IrConstant nullValue =
131 builder.enterConstant(constantSystem.createNull(), node);
132 builder.enterStatement(new IrReturn(nodePosition(node), nullValue));
133 }
134 }
135
136 IrNode visitBlock(Block node) {
137 for (Node n in node.statements.nodes) {
138 n.accept(this);
139 }
140 }
141
142 IrNode visitReturn(Return node) {
143 IrNode value;
144 if (node.expression == null) {
145 if (node.beginToken.value == 'native') return giveup();
146 value = builder.enterConstant(constantSystem.createNull(), node);
147 } else {
148 value = node.expression.accept(this);
149 }
150 builder.branchReturns();
151 return builder.enterStatement(
152 new IrReturn(nodePosition(node), value));
153 }
154
155 IrConstant visitLiteralBool(LiteralBool node) =>
156 builder.enterConstant(constantSystem.createBool(node.value), node);
157
158 IrConstant visitLiteralDouble(LiteralDouble node) =>
159 builder.enterConstant(constantSystem.createDouble(node.value), node);
160
161 IrConstant visitLiteralInt(LiteralInt node) =>
162 builder.enterConstant(constantSystem.createInt(node.value), node);
163
164 IrConstant visitLiteralString(LiteralString node) =>
165 builder.enterConstant(
166 constantSystem.createString(node.dartString, node), node);
167
168 IrConstant visitLiteralNull(LiteralNull node) =>
169 builder.enterConstant(constantSystem.createNull(), node);
170
171 // TODO(lry): other literals.
172 // IrNode visitLiteralList(LiteralList node) => visitExpression(node);
173 // IrNode visitLiteralMap(LiteralMap node) => visitExpression(node);
174 // IrNode visitLiteralMapEntry(LiteralMapEntry node) => visitNode(node);
175 // IrNode visitLiteralSymbol(LiteralSymbol node) => visitExpression(node);
176
177
178 IrNode visitAssert(Send node) {
179 return giveup();
180 }
181
182 IrNode visitClosureSend(Send node) {
183 return giveup();
184 }
185
186 IrNode visitDynamicSend(Send node) {
187 return giveup();
188 }
189
190 IrNode visitGetterSend(Send node) {
191 return giveup();
192 }
193
194 IrNode visitOperatorSend(Send node) {
195 return giveup();
196 }
197
198 IrNode visitStaticSend(Send node) {
199 return giveup();
200 }
201
202 IrNode visitSuperSend(Send node) {
203 return giveup();
204 }
205
206 IrNode visitTypeReferenceSend(Send node) {
207 return giveup();
208 }
209
210 static final String ABORT_IRNODE_BUILDER = "IrNode builder aborted";
211
212 IrNode giveup() => throw ABORT_IRNODE_BUILDER;
213
214 IrNode nullIfGiveup(IrNode action()) {
215 try {
216 return action();
217 } catch(e) {
218 if (e == ABORT_IRNODE_BUILDER) return null;
219 rethrow;
220 }
221 }
222
223 void internalError(String reason, {Node node}) {
224 giveup();
225 }
226 }
227
228 class IrBuilder {
229 final IrNodeBuilderVisitor visitor;
230 IrBuilder(this.visitor);
231
232 // Statements lists for nested blocks.
233 List<List<IrNode>> statementsList = <List<IrNode>>[];
234 List<IrNode> get statements => statementsList.last;
235
236 // TODO(lry): Need to fix this once we actually have branching. Probably
237 // this will be handled by the LocalsHandler, not here.
238 List<bool> returnOnAllBranchesList = <bool>[];
239 bool get returnOnAllBranches => returnOnAllBranchesList.last;
240 void branchReturns() {
241 returnOnAllBranchesList[returnOnAllBranchesList.length - 1] = true;
242 }
243
244 Map<Constant, IrConstant> constants = <Constant, IrConstant>{};
245
246 IrConstant enterConstant(Constant value, Node node) {
ngeoffray 2013/11/21 15:02:05 addConstant?
lukas 2013/11/21 17:14:27 Done.
247 return constants.putIfAbsent(
248 value, () => new IrConstant(visitor.nodePosition(node), value));
249 }
250
251 IrNode enterStatement(IrNode statement) {
ngeoffray 2013/11/21 15:02:05 addStatement?
lukas 2013/11/21 17:14:27 Done.
252 statements.add(statement);
253 return statement;
254 }
255
256 void enterBlock() {
257 statementsList.add(<IrNode>[]);
258 returnOnAllBranchesList.add(false);
259 }
260
261 void exitBlock() {
262 statementsList.removeLast();
263 returnOnAllBranchesList.removeLast();
264 }
265 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698