| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library tree_ir_builder; | 5 library tree_ir_builder; |
| 6 | 6 |
| 7 import '../dart2jslib.dart' as dart2js; | 7 import '../dart2jslib.dart' as dart2js; |
| 8 import '../dart_types.dart'; | 8 import '../dart_types.dart'; |
| 9 import '../elements/elements.dart'; | 9 import '../elements/elements.dart'; |
| 10 import '../cps_ir/cps_ir_nodes.dart' as cps_ir; | 10 import '../cps_ir/cps_ir_nodes.dart' as cps_ir; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 * `LetLabel(L, v, body)` | 36 * `LetLabel(L, v, body)` |
| 37 * | 37 * |
| 38 * Block arguments are later replaced with data flow during the Tree-to-Tree | 38 * Block arguments are later replaced with data flow during the Tree-to-Tree |
| 39 * translation out of SSA. Jumps are eliminated during the Tree-to-Tree | 39 * translation out of SSA. Jumps are eliminated during the Tree-to-Tree |
| 40 * control-flow recognition. | 40 * control-flow recognition. |
| 41 * | 41 * |
| 42 * Otherwise, the output of Builder looks very much like the input. In | 42 * Otherwise, the output of Builder looks very much like the input. In |
| 43 * particular, intermediate values and blocks used for local control flow are | 43 * particular, intermediate values and blocks used for local control flow are |
| 44 * still all named. | 44 * still all named. |
| 45 */ | 45 */ |
| 46 class Builder extends cps_ir.Visitor<Node> { | 46 class Builder implements cps_ir.Visitor<Node> { |
| 47 final dart2js.InternalErrorFunction internalError; | 47 final dart2js.InternalErrorFunction internalError; |
| 48 | 48 |
| 49 /// Maps variable/parameter elements to the Tree variables that represent it. | 49 /// Maps variable/parameter elements to the Tree variables that represent it. |
| 50 final Map<Local, List<Variable>> local2variables = <Local, List<Variable>>{}; | 50 final Map<Local, List<Variable>> local2variables = <Local, List<Variable>>{}; |
| 51 | 51 |
| 52 /// Like [local2variables], except for mutable variables. | 52 /// Like [local2variables], except for mutable variables. |
| 53 final Map<cps_ir.MutableVariable, Variable> local2mutable = | 53 final Map<cps_ir.MutableVariable, Variable> local2mutable = |
| 54 <cps_ir.MutableVariable, Variable>{}; | 54 <cps_ir.MutableVariable, Variable>{}; |
| 55 | 55 |
| 56 // Continuations with more than one use are replaced with Tree labels. This | 56 // Continuations with more than one use are replaced with Tree labels. This |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 317 } | 317 } |
| 318 | 318 |
| 319 if (first == null) { | 319 if (first == null) { |
| 320 first = buildRest(); | 320 first = buildRest(); |
| 321 } else { | 321 } else { |
| 322 current.next = buildRest(); | 322 current.next = buildRest(); |
| 323 } | 323 } |
| 324 return first; | 324 return first; |
| 325 } | 325 } |
| 326 | 326 |
| 327 visitNode(cps_ir.Node node) { | 327 visit(cps_ir.Node node) => node.accept(this); |
| 328 if (node is cps_ir.JsSpecificNode) { | 328 |
| 329 throw "Cannot handle JS specific IR nodes in this visitor"; | 329 unexpectedNode(cps_ir.Node node) { |
| 330 } else { | 330 internalError(CURRENT_ELEMENT_SPANNABLE, 'Unexpected IR node: $node'); |
| 331 throw "Unhandled node: $node"; | 331 } |
| 332 } | 332 |
| 333 // JS-specific nodes are handled by a subclass. |
| 334 visitSetField(cps_ir.SetField node) => unexpectedNode(node); |
| 335 visitIdentical(cps_ir.Identical node) => unexpectedNode(node); |
| 336 visitInterceptor(cps_ir.Interceptor node) => unexpectedNode(node); |
| 337 visitCreateInstance(cps_ir.CreateInstance node) => unexpectedNode(node); |
| 338 visitGetField(cps_ir.GetField node) => unexpectedNode(node); |
| 339 visitCreateBox(cps_ir.CreateBox node) => unexpectedNode(node); |
| 340 |
| 341 // Executable definitions are not visited directly. They have 'build' |
| 342 // functions as entry points. |
| 343 visitFieldDefinition(cps_ir.FieldDefinition node) { |
| 344 return unexpectedNode(node); |
| 345 } |
| 346 visitFunctionDefinition(cps_ir.FunctionDefinition node) { |
| 347 return unexpectedNode(node); |
| 348 } |
| 349 visitConstructorDefinition(cps_ir.ConstructorDefinition node) { |
| 350 return unexpectedNode(node); |
| 333 } | 351 } |
| 334 | 352 |
| 335 Initializer visitFieldInitializer(cps_ir.FieldInitializer node) { | 353 Initializer visitFieldInitializer(cps_ir.FieldInitializer node) { |
| 336 returnContinuation = node.body.returnContinuation; | 354 returnContinuation = node.body.returnContinuation; |
| 337 return new FieldInitializer(node.element, visit(node.body.body)); | 355 return new FieldInitializer(node.element, visit(node.body.body)); |
| 338 } | 356 } |
| 339 | 357 |
| 340 Initializer visitSuperInitializer(cps_ir.SuperInitializer node) { | 358 Initializer visitSuperInitializer(cps_ir.SuperInitializer node) { |
| 341 List<Statement> arguments = | 359 List<Statement> arguments = |
| 342 node.arguments.map((cps_ir.RunnableBody argument) { | 360 node.arguments.map((cps_ir.RunnableBody argument) { |
| (...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 588 bool hasReturnType = !type.returnType.treatAsDynamic; | 606 bool hasReturnType = !type.returnType.treatAsDynamic; |
| 589 if (hasReturnType) { | 607 if (hasReturnType) { |
| 590 // This function cannot occur in expression context. | 608 // This function cannot occur in expression context. |
| 591 // The successor will be filled in by visitLetPrim. | 609 // The successor will be filled in by visitLetPrim. |
| 592 return new FunctionDeclaration(getVariable(node), def, null); | 610 return new FunctionDeclaration(getVariable(node), def, null); |
| 593 } else { | 611 } else { |
| 594 return new FunctionExpression(def); | 612 return new FunctionExpression(def); |
| 595 } | 613 } |
| 596 } | 614 } |
| 597 | 615 |
| 598 Expression visitParameter(cps_ir.Parameter node) { | 616 visitParameter(cps_ir.Parameter node) { |
| 599 // Continuation parameters are not visited (continuations themselves are | 617 // Continuation parameters are not visited (continuations themselves are |
| 600 // not visited yet). | 618 // not visited yet). |
| 601 internalError(CURRENT_ELEMENT_SPANNABLE, 'Unexpected IR node: $node'); | 619 unexpectedNode(node); |
| 602 return null; | |
| 603 } | 620 } |
| 604 | 621 |
| 605 Expression visitContinuation(cps_ir.Continuation node) { | 622 visitContinuation(cps_ir.Continuation node) { |
| 606 // Until continuations with multiple uses are supported, they are not | 623 // Until continuations with multiple uses are supported, they are not |
| 607 // visited. | 624 // visited. |
| 608 internalError(CURRENT_ELEMENT_SPANNABLE, 'Unexpected IR node: $node.'); | 625 unexpectedNode(node); |
| 609 return null; | 626 } |
| 627 |
| 628 visitMutableVariable(cps_ir.MutableVariable node) { |
| 629 // These occur as parameters or bound by LetMutable. They are not visited |
| 630 // directly. |
| 631 unexpectedNode(node); |
| 610 } | 632 } |
| 611 | 633 |
| 612 Expression visitIsTrue(cps_ir.IsTrue node) { | 634 Expression visitIsTrue(cps_ir.IsTrue node) { |
| 613 return getVariableUse(node.value); | 635 return getVariableUse(node.value); |
| 614 } | 636 } |
| 615 } | 637 } |
| 616 | 638 |
| OLD | NEW |