OLD | NEW |
| (Empty) |
1 // Copyright (c) 2014, 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 tree_ir_nodes; | |
6 | |
7 import '../constants/expressions.dart'; | |
8 import '../constants/values.dart' as values; | |
9 import '../cps_ir/cps_ir_nodes.dart' as cps_ir; | |
10 import '../dart_types.dart' show DartType, GenericType; | |
11 import '../elements/elements.dart'; | |
12 import '../universe/universe.dart'; | |
13 import '../universe/universe.dart' show Selector; | |
14 | |
15 | |
16 // The Tree language is the target of translation out of the CPS-based IR. | |
17 // | |
18 // The translation from CPS to Dart consists of several stages. Among the | |
19 // stages are translation to direct style, translation out of SSA, eliminating | |
20 // unnecessary names, recognizing high-level control constructs. Combining | |
21 // these separate concerns is complicated and the constraints of the CPS-based | |
22 // language do not permit a multi-stage translation. | |
23 // | |
24 // For that reason, CPS is translated to the direct-style language Tree. | |
25 // Translation out of SSA, unnaming, and control-flow, as well as 'instruction | |
26 // selection' are performed on the Tree language. | |
27 // | |
28 // In contrast to the CPS-based IR, non-primitive expressions can be named and | |
29 // arguments (to calls, primitives, and blocks) can be arbitrary expressions. | |
30 // | |
31 // Additionally, variables are considered in scope within inner functions; | |
32 // closure variables are thus handled directly instead of using ref cells. | |
33 | |
34 /** | |
35 * The base class of all Tree nodes. | |
36 */ | |
37 abstract class Node { | |
38 } | |
39 | |
40 /** | |
41 * The base class of [Expression]s. | |
42 */ | |
43 abstract class Expression extends Node { | |
44 accept(ExpressionVisitor v); | |
45 | |
46 /// Temporary variable used by [StatementRewriter]. | |
47 /// If set to true, this expression has already had enclosing assignments | |
48 /// propagated into its variables, and should not be processed again. | |
49 /// It is only set for expressions that are known to be in risk of redundant | |
50 /// processing. | |
51 bool processed = false; | |
52 } | |
53 | |
54 abstract class Statement extends Node { | |
55 Statement get next; | |
56 void set next(Statement s); | |
57 accept(StatementVisitor v); | |
58 } | |
59 | |
60 /** | |
61 * Labels name [LabeledStatement]s. | |
62 */ | |
63 class Label { | |
64 // A counter used to generate names. The counter is reset to 0 for each | |
65 // function emitted. | |
66 static int counter = 0; | |
67 static String _newName() => 'L${counter++}'; | |
68 | |
69 String cachedName; | |
70 | |
71 String get name { | |
72 if (cachedName == null) cachedName = _newName(); | |
73 return cachedName; | |
74 } | |
75 | |
76 /// Number of [Break] or [Continue] statements that target this label. | |
77 /// The [Break] constructor will increment this automatically, but the | |
78 /// counter must be decremented by hand when a [Break] becomes orphaned. | |
79 int useCount = 0; | |
80 | |
81 /// The [LabeledStatement] or [WhileTrue] binding this label. | |
82 JumpTarget binding; | |
83 } | |
84 | |
85 /** | |
86 * Variables are [Expression]s. | |
87 */ | |
88 class Variable extends Expression { | |
89 /// Function that declares this variable. | |
90 FunctionDefinition host; | |
91 | |
92 /// [Entity] used for synthesizing a name for the variable. | |
93 /// Different variables may have the same entity. May be null. | |
94 Entity element; | |
95 | |
96 int readCount = 0; | |
97 | |
98 /// Number of places where this variable occurs as: | |
99 /// - left-hand of an [Assign] | |
100 /// - left-hand of a [FunctionDeclaration] | |
101 /// - parameter in a [FunctionDefinition] | |
102 int writeCount = 0; | |
103 | |
104 Variable(this.host, this.element) { | |
105 assert(host != null); | |
106 } | |
107 | |
108 accept(ExpressionVisitor visitor) => visitor.visitVariable(this); | |
109 } | |
110 | |
111 /** | |
112 * Common interface for invocations with arguments. | |
113 */ | |
114 abstract class Invoke { | |
115 List<Expression> get arguments; | |
116 Selector get selector; | |
117 } | |
118 | |
119 /** | |
120 * A call to a static function or getter/setter to a static field. | |
121 * | |
122 * In contrast to the CPS-based IR, the arguments can be arbitrary expressions. | |
123 */ | |
124 class InvokeStatic extends Expression implements Invoke { | |
125 final Entity target; | |
126 final List<Expression> arguments; | |
127 final Selector selector; | |
128 | |
129 InvokeStatic(this.target, this.selector, this.arguments); | |
130 | |
131 accept(ExpressionVisitor visitor) => visitor.visitInvokeStatic(this); | |
132 } | |
133 | |
134 /** | |
135 * A call to a method, operator, getter, setter or index getter/setter. | |
136 * | |
137 * In contrast to the CPS-based IR, the receiver and arguments can be | |
138 * arbitrary expressions. | |
139 */ | |
140 class InvokeMethod extends Expression implements Invoke { | |
141 Expression receiver; | |
142 final Selector selector; | |
143 final List<Expression> arguments; | |
144 | |
145 InvokeMethod(this.receiver, this.selector, this.arguments) { | |
146 assert(receiver != null); | |
147 } | |
148 | |
149 accept(ExpressionVisitor visitor) => visitor.visitInvokeMethod(this); | |
150 } | |
151 | |
152 class InvokeSuperMethod extends Expression implements Invoke { | |
153 final Selector selector; | |
154 final List<Expression> arguments; | |
155 | |
156 InvokeSuperMethod(this.selector, this.arguments) ; | |
157 | |
158 accept(ExpressionVisitor visitor) => visitor.visitInvokeSuperMethod(this); | |
159 } | |
160 | |
161 /** | |
162 * Call to a factory or generative constructor. | |
163 */ | |
164 class InvokeConstructor extends Expression implements Invoke { | |
165 final DartType type; | |
166 final FunctionElement target; | |
167 final List<Expression> arguments; | |
168 final Selector selector; | |
169 final values.ConstantValue constant; | |
170 | |
171 InvokeConstructor(this.type, this.target, this.selector, this.arguments, | |
172 [this.constant]); | |
173 | |
174 ClassElement get targetClass => target.enclosingElement; | |
175 | |
176 accept(ExpressionVisitor visitor) => visitor.visitInvokeConstructor(this); | |
177 } | |
178 | |
179 /// Calls [toString] on each argument and concatenates the results. | |
180 class ConcatenateStrings extends Expression { | |
181 final List<Expression> arguments; | |
182 final values.ConstantValue constant; | |
183 | |
184 ConcatenateStrings(this.arguments, [this.constant]); | |
185 | |
186 accept(ExpressionVisitor visitor) => visitor.visitConcatenateStrings(this); | |
187 } | |
188 | |
189 /** | |
190 * A constant. | |
191 */ | |
192 class Constant extends Expression { | |
193 final ConstantExpression expression; | |
194 | |
195 Constant(this.expression); | |
196 | |
197 Constant.primitive(values.PrimitiveConstantValue primitiveValue) | |
198 : expression = new PrimitiveConstantExpression(primitiveValue); | |
199 | |
200 accept(ExpressionVisitor visitor) => visitor.visitConstant(this); | |
201 | |
202 values.ConstantValue get value => expression.value; | |
203 } | |
204 | |
205 class This extends Expression { | |
206 accept(ExpressionVisitor visitor) => visitor.visitThis(this); | |
207 } | |
208 | |
209 class ReifyTypeVar extends Expression { | |
210 TypeVariableElement typeVariable; | |
211 | |
212 ReifyTypeVar(this.typeVariable); | |
213 | |
214 accept(ExpressionVisitor visitor) => visitor.visitReifyTypeVar(this); | |
215 } | |
216 | |
217 class LiteralList extends Expression { | |
218 final GenericType type; | |
219 final List<Expression> values; | |
220 | |
221 LiteralList(this.type, this.values); | |
222 | |
223 accept(ExpressionVisitor visitor) => visitor.visitLiteralList(this); | |
224 } | |
225 | |
226 class LiteralMapEntry { | |
227 Expression key; | |
228 Expression value; | |
229 | |
230 LiteralMapEntry(this.key, this.value); | |
231 } | |
232 | |
233 class LiteralMap extends Expression { | |
234 final GenericType type; | |
235 final List<LiteralMapEntry> entries; | |
236 | |
237 LiteralMap(this.type, this.entries); | |
238 | |
239 accept(ExpressionVisitor visitor) => visitor.visitLiteralMap(this); | |
240 } | |
241 | |
242 class TypeOperator extends Expression { | |
243 Expression receiver; | |
244 final DartType type; | |
245 final bool isTypeTest; | |
246 | |
247 TypeOperator(this.receiver, this.type, {bool this.isTypeTest}); | |
248 | |
249 accept(ExpressionVisitor visitor) => visitor.visitTypeOperator(this); | |
250 | |
251 String get operator => isTypeTest ? 'is' : 'as'; | |
252 } | |
253 | |
254 /// A conditional expression. | |
255 class Conditional extends Expression { | |
256 Expression condition; | |
257 Expression thenExpression; | |
258 Expression elseExpression; | |
259 | |
260 Conditional(this.condition, this.thenExpression, this.elseExpression); | |
261 | |
262 accept(ExpressionVisitor visitor) => visitor.visitConditional(this); | |
263 } | |
264 | |
265 /// An && or || expression. The operator is internally represented as a boolean | |
266 /// [isAnd] to simplify rewriting of logical operators. | |
267 class LogicalOperator extends Expression { | |
268 Expression left; | |
269 bool isAnd; | |
270 Expression right; | |
271 | |
272 LogicalOperator(this.left, this.right, this.isAnd); | |
273 LogicalOperator.and(this.left, this.right) : isAnd = true; | |
274 LogicalOperator.or(this.left, this.right) : isAnd = false; | |
275 | |
276 String get operator => isAnd ? '&&' : '||'; | |
277 | |
278 accept(ExpressionVisitor visitor) => visitor.visitLogicalOperator(this); | |
279 } | |
280 | |
281 /// Logical negation. | |
282 class Not extends Expression { | |
283 Expression operand; | |
284 | |
285 Not(this.operand); | |
286 | |
287 accept(ExpressionVisitor visitor) => visitor.visitNot(this); | |
288 } | |
289 | |
290 class FunctionExpression extends Expression { | |
291 final FunctionDefinition definition; | |
292 | |
293 FunctionExpression(this.definition) { | |
294 assert(definition.element.type.returnType.treatAsDynamic); | |
295 } | |
296 | |
297 accept(ExpressionVisitor visitor) => visitor.visitFunctionExpression(this); | |
298 } | |
299 | |
300 /// Declares a local function. | |
301 /// Used for functions that may not occur in expression context due to | |
302 /// being recursive or having a return type. | |
303 /// The [variable] must not occur as the left-hand side of an [Assign] or | |
304 /// any other [FunctionDeclaration]. | |
305 class FunctionDeclaration extends Statement { | |
306 Variable variable; | |
307 final FunctionDefinition definition; | |
308 Statement next; | |
309 | |
310 FunctionDeclaration(this.variable, this.definition, this.next) { | |
311 ++variable.writeCount; | |
312 } | |
313 | |
314 accept(StatementVisitor visitor) => visitor.visitFunctionDeclaration(this); | |
315 } | |
316 | |
317 /// A [LabeledStatement] or [WhileTrue] or [WhileCondition]. | |
318 abstract class JumpTarget extends Statement { | |
319 Label get label; | |
320 Statement get body; | |
321 } | |
322 | |
323 /** | |
324 * A labeled statement. Breaks to the label within the labeled statement | |
325 * target the successor statement. | |
326 */ | |
327 class LabeledStatement extends JumpTarget { | |
328 Statement next; | |
329 final Label label; | |
330 Statement body; | |
331 | |
332 LabeledStatement(this.label, this.body, this.next) { | |
333 assert(label.binding == null); | |
334 label.binding = this; | |
335 } | |
336 | |
337 accept(StatementVisitor visitor) => visitor.visitLabeledStatement(this); | |
338 } | |
339 | |
340 /// A [WhileTrue] or [WhileCondition] loop. | |
341 abstract class Loop extends JumpTarget { | |
342 } | |
343 | |
344 /** | |
345 * A labeled while(true) loop. | |
346 */ | |
347 class WhileTrue extends Loop { | |
348 final Label label; | |
349 Statement body; | |
350 | |
351 WhileTrue(this.label, this.body) { | |
352 assert(label.binding == null); | |
353 label.binding = this; | |
354 } | |
355 | |
356 Statement get next => null; | |
357 void set next(Statement s) => throw 'UNREACHABLE'; | |
358 | |
359 accept(StatementVisitor visitor) => visitor.visitWhileTrue(this); | |
360 } | |
361 | |
362 /** | |
363 * A while loop with a condition. If the condition is false, control resumes | |
364 * at the [next] statement. | |
365 * | |
366 * It is NOT valid to target this statement with a [Break]. | |
367 * The only way to reach [next] is for the condition to evaluate to false. | |
368 * | |
369 * [WhileCondition] statements are introduced in the [LoopRewriter] and is | |
370 * assumed not to occur before then. | |
371 */ | |
372 class WhileCondition extends Loop { | |
373 final Label label; | |
374 Expression condition; | |
375 Statement body; | |
376 Statement next; | |
377 | |
378 WhileCondition(this.label, this.condition, this.body, | |
379 this.next) { | |
380 assert(label.binding == null); | |
381 label.binding = this; | |
382 } | |
383 | |
384 accept(StatementVisitor visitor) => visitor.visitWhileCondition(this); | |
385 } | |
386 | |
387 /// A [Break] or [Continue] statement. | |
388 abstract class Jump extends Statement { | |
389 Label get target; | |
390 } | |
391 | |
392 /** | |
393 * A break from an enclosing [LabeledStatement]. The break targets the | |
394 * labeled statement's successor statement. | |
395 */ | |
396 class Break extends Jump { | |
397 final Label target; | |
398 | |
399 Statement get next => null; | |
400 void set next(Statement s) => throw 'UNREACHABLE'; | |
401 | |
402 Break(this.target) { | |
403 ++target.useCount; | |
404 } | |
405 | |
406 accept(StatementVisitor visitor) => visitor.visitBreak(this); | |
407 } | |
408 | |
409 /** | |
410 * A continue to an enclosing [WhileTrue] or [WhileCondition] loop. | |
411 * The continue targets the loop's body. | |
412 */ | |
413 class Continue extends Jump { | |
414 final Label target; | |
415 | |
416 Statement get next => null; | |
417 void set next(Statement s) => throw 'UNREACHABLE'; | |
418 | |
419 Continue(this.target) { | |
420 ++target.useCount; | |
421 } | |
422 | |
423 accept(StatementVisitor visitor) => visitor.visitContinue(this); | |
424 } | |
425 | |
426 /** | |
427 * An assignments of an [Expression] to a [Variable]. | |
428 * | |
429 * In contrast to the CPS-based IR, non-primitive expressions can be assigned | |
430 * to variables. | |
431 */ | |
432 class Assign extends Statement { | |
433 Statement next; | |
434 Variable variable; | |
435 Expression definition; | |
436 | |
437 /// If true, this declares a new copy of the closure variable. | |
438 /// The consequences are similar to [cps_ir.SetClosureVariable]. | |
439 /// All uses of the variable must be nested inside the [next] statement. | |
440 bool isDeclaration; | |
441 | |
442 Assign(this.variable, this.definition, this.next, | |
443 { this.isDeclaration: false }) { | |
444 variable.writeCount++; | |
445 } | |
446 | |
447 bool get hasExactlyOneUse => variable.readCount == 1; | |
448 | |
449 accept(StatementVisitor visitor) => visitor.visitAssign(this); | |
450 } | |
451 | |
452 /** | |
453 * A return exit from the function. | |
454 * | |
455 * In contrast to the CPS-based IR, the return value is an arbitrary | |
456 * expression. | |
457 */ | |
458 class Return extends Statement { | |
459 /// Should not be null. Use [Constant] with [NullConstantValue] for void | |
460 /// returns. | |
461 Expression value; | |
462 | |
463 Statement get next => null; | |
464 void set next(Statement s) => throw 'UNREACHABLE'; | |
465 | |
466 Return(this.value); | |
467 | |
468 accept(StatementVisitor visitor) => visitor.visitReturn(this); | |
469 } | |
470 | |
471 /** | |
472 * A conditional branch based on the true value of an [Expression]. | |
473 */ | |
474 class If extends Statement { | |
475 Expression condition; | |
476 Statement thenStatement; | |
477 Statement elseStatement; | |
478 | |
479 Statement get next => null; | |
480 void set next(Statement s) => throw 'UNREACHABLE'; | |
481 | |
482 If(this.condition, this.thenStatement, this.elseStatement); | |
483 | |
484 accept(StatementVisitor visitor) => visitor.visitIf(this); | |
485 } | |
486 | |
487 class ExpressionStatement extends Statement { | |
488 Statement next; | |
489 Expression expression; | |
490 | |
491 ExpressionStatement(this.expression, this.next); | |
492 | |
493 accept(StatementVisitor visitor) => visitor.visitExpressionStatement(this); | |
494 } | |
495 | |
496 class FunctionDefinition extends Node { | |
497 final FunctionElement element; | |
498 final List<Variable> parameters; | |
499 Statement body; | |
500 final List<ConstDeclaration> localConstants; | |
501 final List<ConstantExpression> defaultParameterValues; | |
502 | |
503 FunctionDefinition(this.element, this.parameters, this.body, | |
504 this.localConstants, this.defaultParameterValues); | |
505 | |
506 /// Returns `true` if this function is abstract. | |
507 /// | |
508 /// If `true` [body] is `null` and [localConstants] is empty. | |
509 bool get isAbstract => body == null; | |
510 } | |
511 | |
512 abstract class ExpressionVisitor<E> { | |
513 E visitExpression(Expression e) => e.accept(this); | |
514 E visitVariable(Variable node); | |
515 E visitInvokeStatic(InvokeStatic node); | |
516 E visitInvokeMethod(InvokeMethod node); | |
517 E visitInvokeSuperMethod(InvokeSuperMethod node); | |
518 E visitInvokeConstructor(InvokeConstructor node); | |
519 E visitConcatenateStrings(ConcatenateStrings node); | |
520 E visitConstant(Constant node); | |
521 E visitThis(This node); | |
522 E visitReifyTypeVar(ReifyTypeVar node); | |
523 E visitConditional(Conditional node); | |
524 E visitLogicalOperator(LogicalOperator node); | |
525 E visitNot(Not node); | |
526 E visitLiteralList(LiteralList node); | |
527 E visitLiteralMap(LiteralMap node); | |
528 E visitTypeOperator(TypeOperator node); | |
529 E visitFunctionExpression(FunctionExpression node); | |
530 } | |
531 | |
532 abstract class StatementVisitor<S> { | |
533 S visitStatement(Statement s) => s.accept(this); | |
534 S visitLabeledStatement(LabeledStatement node); | |
535 S visitAssign(Assign node); | |
536 S visitReturn(Return node); | |
537 S visitBreak(Break node); | |
538 S visitContinue(Continue node); | |
539 S visitIf(If node); | |
540 S visitWhileTrue(WhileTrue node); | |
541 S visitWhileCondition(WhileCondition node); | |
542 S visitFunctionDeclaration(FunctionDeclaration node); | |
543 S visitExpressionStatement(ExpressionStatement node); | |
544 } | |
545 | |
546 abstract class Visitor<S,E> implements ExpressionVisitor<E>, | |
547 StatementVisitor<S> { | |
548 E visitExpression(Expression e) => e.accept(this); | |
549 S visitStatement(Statement s) => s.accept(this); | |
550 } | |
551 | |
552 class RecursiveVisitor extends Visitor { | |
553 visitFunctionDefinition(FunctionDefinition node) { | |
554 visitStatement(node.body); | |
555 } | |
556 | |
557 visitVariable(Variable node) {} | |
558 | |
559 visitInvokeStatic(InvokeStatic node) { | |
560 node.arguments.forEach(visitExpression); | |
561 } | |
562 | |
563 visitInvokeMethod(InvokeMethod node) { | |
564 visitExpression(node.receiver); | |
565 node.arguments.forEach(visitExpression); | |
566 } | |
567 | |
568 visitInvokeSuperMethod(InvokeSuperMethod node) { | |
569 node.arguments.forEach(visitExpression); | |
570 } | |
571 | |
572 visitInvokeConstructor(InvokeConstructor node) { | |
573 node.arguments.forEach(visitExpression); | |
574 } | |
575 | |
576 visitConcatenateStrings(ConcatenateStrings node) { | |
577 node.arguments.forEach(visitExpression); | |
578 } | |
579 | |
580 visitConstant(Constant node) {} | |
581 | |
582 visitThis(This node) {} | |
583 | |
584 visitReifyTypeVar(ReifyTypeVar node) {} | |
585 | |
586 visitConditional(Conditional node) { | |
587 visitExpression(node.condition); | |
588 visitExpression(node.thenExpression); | |
589 visitExpression(node.elseExpression); | |
590 } | |
591 | |
592 visitLogicalOperator(LogicalOperator node) { | |
593 visitExpression(node.left); | |
594 visitExpression(node.right); | |
595 } | |
596 | |
597 visitNot(Not node) { | |
598 visitExpression(node.operand); | |
599 } | |
600 | |
601 visitLiteralList(LiteralList node) { | |
602 node.values.forEach(visitExpression); | |
603 } | |
604 | |
605 visitLiteralMap(LiteralMap node) { | |
606 node.entries.forEach((LiteralMapEntry entry) { | |
607 visitExpression(entry.key); | |
608 visitExpression(entry.value); | |
609 }); | |
610 } | |
611 | |
612 visitTypeOperator(TypeOperator node) { | |
613 visitExpression(node.receiver); | |
614 } | |
615 | |
616 visitFunctionExpression(FunctionExpression node) { | |
617 visitFunctionDefinition(node.definition); | |
618 } | |
619 | |
620 visitLabeledStatement(LabeledStatement node) { | |
621 visitStatement(node.body); | |
622 visitStatement(node.next); | |
623 } | |
624 | |
625 visitAssign(Assign node) { | |
626 visitExpression(node.definition); | |
627 visitVariable(node.variable); | |
628 visitStatement(node.next); | |
629 } | |
630 | |
631 visitReturn(Return node) { | |
632 visitExpression(node.value); | |
633 } | |
634 | |
635 visitBreak(Break node) {} | |
636 | |
637 visitContinue(Continue node) {} | |
638 | |
639 visitIf(If node) { | |
640 visitExpression(node.condition); | |
641 visitStatement(node.thenStatement); | |
642 visitStatement(node.elseStatement); | |
643 } | |
644 | |
645 visitWhileTrue(WhileTrue node) { | |
646 visitStatement(node.body); | |
647 } | |
648 | |
649 visitWhileCondition(WhileCondition node) { | |
650 visitExpression(node.condition); | |
651 visitStatement(node.body); | |
652 visitStatement(node.next); | |
653 } | |
654 | |
655 visitFunctionDeclaration(FunctionDeclaration node) { | |
656 visitFunctionDefinition(node.definition); | |
657 visitStatement(node.next); | |
658 } | |
659 | |
660 visitExpressionStatement(ExpressionStatement node) { | |
661 visitExpression(node.expression); | |
662 visitStatement(node.next); | |
663 } | |
664 } | |
OLD | NEW |