| 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; |
| 11 import 'tree_ir_nodes.dart'; | 11 import 'tree_ir_nodes.dart'; |
| 12 import '../js_backend/codegen/glue.dart'; |
| 12 | 13 |
| 13 /** | 14 /** |
| 14 * Builder translates from CPS-based IR to direct-style Tree. | 15 * Builder translates from CPS-based IR to direct-style Tree. |
| 15 * | 16 * |
| 16 * A call `Invoke(fun, cont, args)`, where cont is a singly-referenced | 17 * A call `Invoke(fun, cont, args)`, where cont is a singly-referenced |
| 17 * non-exit continuation `Cont(v, body)` is translated into a direct-style call | 18 * non-exit continuation `Cont(v, body)` is translated into a direct-style call |
| 18 * whose value is bound in the continuation body: | 19 * whose value is bound in the continuation body: |
| 19 * | 20 * |
| 20 * `LetVal(v, Invoke(fun, args), body)` | 21 * `LetVal(v, Invoke(fun, args), body)` |
| 21 * | 22 * |
| (...skipping 14 matching lines...) Expand all Loading... |
| 36 * | 37 * |
| 37 * 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 |
| 38 * 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 |
| 39 * control-flow recognition. | 40 * control-flow recognition. |
| 40 * | 41 * |
| 41 * 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 |
| 42 * particular, intermediate values and blocks used for local control flow are | 43 * particular, intermediate values and blocks used for local control flow are |
| 43 * still all named. | 44 * still all named. |
| 44 */ | 45 */ |
| 45 class Builder extends cps_ir.Visitor<Node> { | 46 class Builder extends cps_ir.Visitor<Node> { |
| 47 // TODO(karlklose): remove the compiler. |
| 46 final dart2js.Compiler compiler; | 48 final dart2js.Compiler compiler; |
| 49 final Glue glue; |
| 47 | 50 |
| 48 /// Maps variable/parameter elements to the Tree variables that represent it. | 51 /// Maps variable/parameter elements to the Tree variables that represent it. |
| 49 final Map<Element, List<Variable>> element2variables = | 52 final Map<Element, List<Variable>> element2variables = |
| 50 <Element,List<Variable>>{}; | 53 <Element,List<Variable>>{}; |
| 51 | 54 |
| 52 /// Like [element2variables], except for closure variables. | 55 /// Like [element2variables], except for closure variables. |
| 53 final Map<cps_ir.ClosureVariable, Variable> local2closure = | 56 final Map<cps_ir.ClosureVariable, Variable> local2closure = |
| 54 <cps_ir.ClosureVariable, Variable>{}; | 57 <cps_ir.ClosureVariable, Variable>{}; |
| 55 | 58 |
| 56 // Continuations with more than one use are replaced with Tree labels. This | 59 // Continuations with more than one use are replaced with Tree labels. This |
| 57 // is the mapping from continuations to labels. | 60 // is the mapping from continuations to labels. |
| 58 final Map<cps_ir.Continuation, Label> labels = <cps_ir.Continuation, Label>{}; | 61 final Map<cps_ir.Continuation, Label> labels = <cps_ir.Continuation, Label>{}; |
| 59 | 62 |
| 60 ExecutableElement currentElement; | 63 ExecutableElement currentElement; |
| 61 cps_ir.Continuation returnContinuation; | 64 cps_ir.Continuation returnContinuation; |
| 62 | 65 |
| 63 Builder parent; | 66 Builder parent; |
| 64 | 67 |
| 65 Builder(this.compiler); | 68 Builder(this.glue, this.compiler); |
| 66 | 69 |
| 67 Builder.inner(Builder parent) | 70 Builder.inner(Builder parent) |
| 68 : this.parent = parent, | 71 : this.parent = parent, |
| 72 this.glue = parent.glue, |
| 69 compiler = parent.compiler; | 73 compiler = parent.compiler; |
| 70 | 74 |
| 71 /// Variable used in [buildPhiAssignments] as a temporary when swapping | 75 /// Variable used in [buildPhiAssignments] as a temporary when swapping |
| 72 /// variables. | 76 /// variables. |
| 73 Variable phiTempVar; | 77 Variable phiTempVar; |
| 74 | 78 |
| 75 Variable getClosureVariable(cps_ir.ClosureVariable irVariable) { | 79 Variable getClosureVariable(cps_ir.ClosureVariable irVariable) { |
| 76 if (irVariable.host != currentElement) { | 80 if (irVariable.host != currentElement) { |
| 77 return parent.getClosureVariable(irVariable); | 81 return parent.getClosureVariable(irVariable); |
| 78 } | 82 } |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 155 phiTempVar = new Variable(node.element, null); | 159 phiTempVar = new Variable(node.element, null); |
| 156 body = visit(node.body); | 160 body = visit(node.body); |
| 157 } | 161 } |
| 158 | 162 |
| 159 return new FunctionDefinition(node.element, parameters, | 163 return new FunctionDefinition(node.element, parameters, |
| 160 body, node.localConstants, node.defaultParameterValues); | 164 body, node.localConstants, node.defaultParameterValues); |
| 161 } | 165 } |
| 162 | 166 |
| 163 List<Expression> translateArguments(List<cps_ir.Reference> args) { | 167 List<Expression> translateArguments(List<cps_ir.Reference> args) { |
| 164 return new List<Expression>.generate(args.length, | 168 return new List<Expression>.generate(args.length, |
| 165 (int index) => getVariableReference(args[index])); | 169 (int index) => getVariableReference(args[index]), |
| 170 growable: false); |
| 166 } | 171 } |
| 167 | 172 |
| 168 List<Variable> translatePhiArguments(List<cps_ir.Reference> args) { | 173 List<Variable> translatePhiArguments(List<cps_ir.Reference> args) { |
| 169 return new List<Variable>.generate(args.length, | 174 return new List<Variable>.generate(args.length, |
| 170 (int index) => getVariableReference(args[index])); | 175 (int index) => getVariableReference(args[index])); |
| 171 } | 176 } |
| 172 | 177 |
| 173 Statement buildContinuationAssignment( | 178 Statement buildContinuationAssignment( |
| 174 cps_ir.Parameter parameter, | 179 cps_ir.Parameter parameter, |
| 175 Expression argument, | 180 Expression argument, |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 309 } | 314 } |
| 310 | 315 |
| 311 Statement visitInvokeStatic(cps_ir.InvokeStatic node) { | 316 Statement visitInvokeStatic(cps_ir.InvokeStatic node) { |
| 312 // Calls are translated to direct style. | 317 // Calls are translated to direct style. |
| 313 List<Expression> arguments = translateArguments(node.arguments); | 318 List<Expression> arguments = translateArguments(node.arguments); |
| 314 Expression invoke = new InvokeStatic(node.target, node.selector, arguments); | 319 Expression invoke = new InvokeStatic(node.target, node.selector, arguments); |
| 315 return continueWithExpression(node.continuation, invoke); | 320 return continueWithExpression(node.continuation, invoke); |
| 316 } | 321 } |
| 317 | 322 |
| 318 Statement visitInvokeMethod(cps_ir.InvokeMethod node) { | 323 Statement visitInvokeMethod(cps_ir.InvokeMethod node) { |
| 319 Expression receiver = getVariableReference(node.receiver); | 324 Expression invoke = new InvokeMethod(getVariableReference(node.receiver), |
| 320 List<Expression> arguments = translateArguments(node.arguments); | 325 node.selector, |
| 321 Expression invoke = new InvokeMethod(receiver, node.selector, arguments); | 326 translateArguments(node.arguments)); |
| 322 return continueWithExpression(node.continuation, invoke); | 327 return continueWithExpression(node.continuation, invoke); |
| 323 } | 328 } |
| 324 | 329 |
| 325 Statement visitInvokeSuperMethod(cps_ir.InvokeSuperMethod node) { | 330 Statement visitInvokeSuperMethod(cps_ir.InvokeSuperMethod node) { |
| 326 List<Expression> arguments = translateArguments(node.arguments); | 331 List<Expression> arguments = translateArguments(node.arguments); |
| 327 Expression invoke = new InvokeSuperMethod(node.selector, arguments); | 332 Expression invoke = new InvokeSuperMethod(node.selector, arguments); |
| 328 return continueWithExpression(node.continuation, invoke); | 333 return continueWithExpression(node.continuation, invoke); |
| 329 } | 334 } |
| 330 | 335 |
| 331 Statement visitConcatenateStrings(cps_ir.ConcatenateStrings node) { | 336 Statement visitConcatenateStrings(cps_ir.ConcatenateStrings node) { |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 473 // The successor will be filled in by visitLetPrim. | 478 // The successor will be filled in by visitLetPrim. |
| 474 return new FunctionDeclaration(getVariable(node), def, null); | 479 return new FunctionDeclaration(getVariable(node), def, null); |
| 475 } else { | 480 } else { |
| 476 return new FunctionExpression(def); | 481 return new FunctionExpression(def); |
| 477 } | 482 } |
| 478 } | 483 } |
| 479 | 484 |
| 480 Expression visitParameter(cps_ir.Parameter node) { | 485 Expression visitParameter(cps_ir.Parameter node) { |
| 481 // Continuation parameters are not visited (continuations themselves are | 486 // Continuation parameters are not visited (continuations themselves are |
| 482 // not visited yet). | 487 // not visited yet). |
| 483 compiler.internalError(compiler.currentElement, 'Unexpected IR node.'); | 488 compiler.internalError(compiler.currentElement, |
| 489 'Unexpected IR node: $node'); |
| 484 return null; | 490 return null; |
| 485 } | 491 } |
| 486 | 492 |
| 487 Expression visitContinuation(cps_ir.Continuation node) { | 493 Expression visitContinuation(cps_ir.Continuation node) { |
| 488 // Until continuations with multiple uses are supported, they are not | 494 // Until continuations with multiple uses are supported, they are not |
| 489 // visited. | 495 // visited. |
| 490 compiler.internalError(compiler.currentElement, 'Unexpected IR node.'); | 496 compiler.internalError(compiler.currentElement, |
| 497 'Unexpected IR node: $node.'); |
| 491 return null; | 498 return null; |
| 492 } | 499 } |
| 493 | 500 |
| 494 Expression visitIsTrue(cps_ir.IsTrue node) { | 501 Expression visitIsTrue(cps_ir.IsTrue node) { |
| 495 return getVariableReference(node.value); | 502 return getVariableReference(node.value); |
| 496 } | 503 } |
| 497 | 504 |
| 498 dart2js.Selector get identicalSelector { | 505 dart2js.Selector get identicalSelector { |
| 499 return new dart2js.Selector.call('identical', null, 2); | 506 return new dart2js.Selector.call('identical', null, 2); |
| 500 } | 507 } |
| 501 | 508 |
| 502 Expression visitIdentical(cps_ir.Identical node) { | 509 Expression visitIdentical(cps_ir.Identical node) { |
| 503 return new InvokeStatic( | 510 return new InvokeStatic( |
| 504 compiler.identicalFunction, | 511 compiler.identicalFunction, |
| 505 identicalSelector, | 512 identicalSelector, |
| 506 <Expression>[getVariableReference(node.left), | 513 <Expression>[getVariableReference(node.left), |
| 507 getVariableReference(node.right)]); | 514 getVariableReference(node.right)]); |
| 508 } | 515 } |
| 516 |
| 517 Expression visitInterceptor(cps_ir.Interceptor node) { |
| 518 Element getInterceptor = glue.getInterceptorMethod; |
| 519 glue.registerUseInterceptorInCodegen(); |
| 520 return new InvokeStatic( |
| 521 getInterceptor, |
| 522 new dart2js.Selector.fromElement(getInterceptor), |
| 523 <Expression>[getVariableReference(node.input)]); |
| 524 } |
| 509 } | 525 } |
| 510 | 526 |
| OLD | NEW |