| 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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 Variable addMutableVariable(cps_ir.MutableVariable irVariable) { | 75 Variable addMutableVariable(cps_ir.MutableVariable irVariable) { |
| 76 if (irVariable.host != currentElement) { | 76 if (irVariable.host != currentElement) { |
| 77 return parent.addMutableVariable(irVariable); | 77 return parent.addMutableVariable(irVariable); |
| 78 } | 78 } |
| 79 assert(!local2mutable.containsKey(irVariable)); | 79 assert(!local2mutable.containsKey(irVariable)); |
| 80 Variable variable = new Variable(currentElement, irVariable.hint); | 80 Variable variable = new Variable(currentElement, irVariable.hint); |
| 81 local2mutable[irVariable] = variable; | 81 local2mutable[irVariable] = variable; |
| 82 return variable; | 82 return variable; |
| 83 } | 83 } |
| 84 | 84 |
| 85 Variable getMutableVariableReference( | 85 Variable getMutableVariable(cps_ir.MutableVariable mutableVariable) { |
| 86 if (mutableVariable.host != currentElement) { |
| 87 return parent.getMutableVariable(mutableVariable); |
| 88 } |
| 89 return local2mutable[mutableVariable]; |
| 90 } |
| 91 |
| 92 VariableUse getMutableVariableUse( |
| 86 cps_ir.Reference<cps_ir.MutableVariable> reference) { | 93 cps_ir.Reference<cps_ir.MutableVariable> reference) { |
| 87 if (reference.definition.host != currentElement) { | 94 Variable variable = getMutableVariable(reference.definition); |
| 88 return parent.getMutableVariableReference(reference); | 95 return new VariableUse(variable); |
| 89 } | |
| 90 Variable variable = local2mutable[reference.definition]; | |
| 91 ++variable.readCount; | |
| 92 return variable; | |
| 93 } | 96 } |
| 94 | 97 |
| 95 /// Obtains the variable representing the given primitive. Returns null for | 98 /// Obtains the variable representing the given primitive. Returns null for |
| 96 /// primitives that have no reference and do not need a variable. | 99 /// primitives that have no reference and do not need a variable. |
| 97 Variable getVariable(cps_ir.Primitive primitive) { | 100 Variable getVariable(cps_ir.Primitive primitive) { |
| 98 if (primitive.registerIndex == null) { | 101 if (primitive.registerIndex == null) { |
| 99 return null; // variable is unused | 102 return null; // variable is unused |
| 100 } | 103 } |
| 101 List<Variable> variables = local2variables.putIfAbsent(primitive.hint, | 104 List<Variable> variables = local2variables.putIfAbsent(primitive.hint, |
| 102 () => <Variable>[]); | 105 () => <Variable>[]); |
| 103 while (variables.length <= primitive.registerIndex) { | 106 while (variables.length <= primitive.registerIndex) { |
| 104 variables.add(new Variable(currentElement, primitive.hint)); | 107 variables.add(new Variable(currentElement, primitive.hint)); |
| 105 } | 108 } |
| 106 return variables[primitive.registerIndex]; | 109 return variables[primitive.registerIndex]; |
| 107 } | 110 } |
| 108 | 111 |
| 109 /// Obtains a reference to the tree Variable corresponding to the IR primitive | 112 /// Obtains a reference to the tree Variable corresponding to the IR primitive |
| 110 /// referred to by [reference]. | 113 /// referred to by [reference]. |
| 111 /// This increments the reference count for the given variable, so the | 114 /// This increments the reference count for the given variable, so the |
| 112 /// returned expression must be used in the tree. | 115 /// returned expression must be used in the tree. |
| 113 Expression getVariableReference(cps_ir.Reference reference) { | 116 VariableUse getVariableUse(cps_ir.Reference<cps_ir.Primitive> reference) { |
| 114 Variable variable = getVariable(reference.definition); | 117 Variable variable = getVariable(reference.definition); |
| 115 if (variable == null) { | 118 if (variable == null) { |
| 116 internalError( | 119 internalError( |
| 117 CURRENT_ELEMENT_SPANNABLE, | 120 CURRENT_ELEMENT_SPANNABLE, |
| 118 "Reference to ${reference.definition} has no register"); | 121 "Reference to ${reference.definition} has no register"); |
| 119 } | 122 } |
| 120 ++variable.readCount; | 123 return new VariableUse(variable); |
| 121 return variable; | |
| 122 } | 124 } |
| 123 | 125 |
| 124 ExecutableDefinition build(cps_ir.ExecutableDefinition node) { | 126 ExecutableDefinition build(cps_ir.ExecutableDefinition node) { |
| 125 if (node is cps_ir.FieldDefinition) { | 127 if (node is cps_ir.FieldDefinition) { |
| 126 return buildField(node); | 128 return buildField(node); |
| 127 } else if (node is cps_ir.ConstructorDefinition) { | 129 } else if (node is cps_ir.ConstructorDefinition) { |
| 128 return buildConstructor(node); | 130 return buildConstructor(node); |
| 129 } else { | 131 } else { |
| 130 assert(dart2js.invariant( | 132 assert(dart2js.invariant( |
| 131 CURRENT_ELEMENT_SPANNABLE, | 133 CURRENT_ELEMENT_SPANNABLE, |
| (...skipping 20 matching lines...) Expand all Loading... |
| 152 Variable addFunctionParameter(cps_ir.Definition variable) { | 154 Variable addFunctionParameter(cps_ir.Definition variable) { |
| 153 if (variable is cps_ir.Parameter) { | 155 if (variable is cps_ir.Parameter) { |
| 154 return getVariable(variable); | 156 return getVariable(variable); |
| 155 } else { | 157 } else { |
| 156 return addMutableVariable(variable as cps_ir.MutableVariable); | 158 return addMutableVariable(variable as cps_ir.MutableVariable); |
| 157 } | 159 } |
| 158 } | 160 } |
| 159 | 161 |
| 160 FunctionDefinition buildFunction(cps_ir.FunctionDefinition node) { | 162 FunctionDefinition buildFunction(cps_ir.FunctionDefinition node) { |
| 161 currentElement = node.element; | 163 currentElement = node.element; |
| 162 List<Variable> parameters = <Variable>[]; | 164 List<Variable> parameters = |
| 163 for (cps_ir.Definition p in node.parameters) { | 165 node.parameters.map(addFunctionParameter).toList(); |
| 164 Variable parameter = addFunctionParameter(p); | |
| 165 assert(parameter != null); | |
| 166 ++parameter.writeCount; // Being a parameter counts as a write. | |
| 167 parameters.add(parameter); | |
| 168 } | |
| 169 | |
| 170 Statement body; | 166 Statement body; |
| 171 if (!node.isAbstract) { | 167 if (!node.isAbstract) { |
| 172 returnContinuation = node.body.returnContinuation; | 168 returnContinuation = node.body.returnContinuation; |
| 173 phiTempVar = new Variable(node.element, null); | 169 phiTempVar = new Variable(node.element, null); |
| 174 body = visit(node.body); | 170 body = visit(node.body); |
| 175 } | 171 } |
| 176 | 172 |
| 177 return new FunctionDefinition(node.element, parameters, | 173 return new FunctionDefinition(node.element, parameters, |
| 178 body, node.localConstants, node.defaultParameterValues); | 174 body, node.localConstants, node.defaultParameterValues); |
| 179 } | 175 } |
| 180 | 176 |
| 181 ConstructorDefinition buildConstructor(cps_ir.ConstructorDefinition node) { | 177 ConstructorDefinition buildConstructor(cps_ir.ConstructorDefinition node) { |
| 182 currentElement = node.element; | 178 currentElement = node.element; |
| 183 List<Variable> parameters = <Variable>[]; | 179 List<Variable> parameters = |
| 184 for (cps_ir.Definition p in node.parameters) { | 180 node.parameters.map(addFunctionParameter).toList(); |
| 185 Variable parameter = addFunctionParameter(p); | |
| 186 assert(parameter != null); | |
| 187 ++parameter.writeCount; // Being a parameter counts as a write. | |
| 188 parameters.add(parameter); | |
| 189 } | |
| 190 List<Initializer> initializers; | 181 List<Initializer> initializers; |
| 191 Statement body; | 182 Statement body; |
| 192 if (!node.isAbstract) { | 183 if (!node.isAbstract) { |
| 193 initializers = node.initializers.map(visit).toList(); | 184 initializers = node.initializers.map(visit).toList(); |
| 194 returnContinuation = node.body.returnContinuation; | 185 returnContinuation = node.body.returnContinuation; |
| 195 | 186 |
| 196 phiTempVar = new Variable(node.element, null); | 187 phiTempVar = new Variable(node.element, null); |
| 197 body = visit(node.body); | 188 body = visit(node.body); |
| 198 } | 189 } |
| 199 | 190 |
| 200 return new ConstructorDefinition(node.element, parameters, | 191 return new ConstructorDefinition(node.element, parameters, |
| 201 body, initializers, node.localConstants, node.defaultParameterValues); | 192 body, initializers, node.localConstants, node.defaultParameterValues); |
| 202 } | 193 } |
| 203 | 194 |
| 204 /// Returns a list of variables corresponding to the arguments to a method | 195 /// Returns a list of variables corresponding to the arguments to a method |
| 205 /// call or similar construct. | 196 /// call or similar construct. |
| 206 /// | 197 /// |
| 207 /// The `readCount` for these variables will be incremented. | 198 /// The `readCount` for these variables will be incremented. |
| 208 /// | 199 /// |
| 209 /// The list will be typed as a list of [Expression] to allow inplace updates | 200 /// The list will be typed as a list of [Expression] to allow inplace updates |
| 210 /// on the list during the rewrite phases. | 201 /// on the list during the rewrite phases. |
| 211 List<Expression> translateArguments(List<cps_ir.Reference> args) { | 202 List<Expression> translateArguments(List<cps_ir.Reference> args) { |
| 212 return new List<Expression>.generate(args.length, | 203 return new List<Expression>.generate(args.length, |
| 213 (int index) => getVariableReference(args[index]), | 204 (int index) => getVariableUse(args[index]), |
| 214 growable: false); | 205 growable: false); |
| 215 } | 206 } |
| 216 | 207 |
| 217 /// Returns the list of variables corresponding to the arguments to a join | 208 /// Returns the list of variables corresponding to the arguments to a join |
| 218 /// continuation. | 209 /// continuation. |
| 219 /// | 210 /// |
| 220 /// The `readCount` of these variables will not be incremented. Instead, | 211 /// The `readCount` of these variables will not be incremented. Instead, |
| 221 /// [buildPhiAssignments] will handle the increment, if necessary. | 212 /// [buildPhiAssignments] will handle the increment, if necessary. |
| 222 List<Variable> translatePhiArguments(List<cps_ir.Reference> args) { | 213 List<Variable> translatePhiArguments(List<cps_ir.Reference> args) { |
| 223 return new List<Variable>.generate(args.length, | 214 return new List<Variable>.generate(args.length, |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 } | 255 } |
| 265 List<int> list = rightHand[arg]; | 256 List<int> list = rightHand[arg]; |
| 266 if (list == null) { | 257 if (list == null) { |
| 267 rightHand[arg] = list = <int>[]; | 258 rightHand[arg] = list = <int>[]; |
| 268 } | 259 } |
| 269 list.add(i); | 260 list.add(i); |
| 270 } | 261 } |
| 271 | 262 |
| 272 Statement first, current; | 263 Statement first, current; |
| 273 void addAssignment(Variable dst, Variable src) { | 264 void addAssignment(Variable dst, Variable src) { |
| 274 ++src.readCount; | |
| 275 // `dst.writeCount` will be updated by the Assign constructor. | |
| 276 if (first == null) { | 265 if (first == null) { |
| 277 first = current = new Assign(dst, src, null); | 266 first = current = new Assign(dst, new VariableUse(src), null); |
| 278 } else { | 267 } else { |
| 279 current = current.next = new Assign(dst, src, null); | 268 current = current.next = new Assign(dst, new VariableUse(src), null); |
| 280 } | 269 } |
| 281 } | 270 } |
| 282 | 271 |
| 283 List<Variable> assignmentSrc = new List<Variable>(parameters.length); | 272 List<Variable> assignmentSrc = new List<Variable>(parameters.length); |
| 284 List<bool> done = new List<bool>(parameters.length); | 273 List<bool> done = new List<bool>(parameters.length); |
| 285 void visitAssignment(int i) { | 274 void visitAssignment(int i) { |
| 286 if (done[i] == true) { | 275 if (done[i] == true) { |
| 287 return; | 276 return; |
| 288 } | 277 } |
| 289 Variable param = getVariable(parameters[i]); | 278 Variable param = getVariable(parameters[i]); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 } | 391 } |
| 403 | 392 |
| 404 Statement visitInvokeStatic(cps_ir.InvokeStatic node) { | 393 Statement visitInvokeStatic(cps_ir.InvokeStatic node) { |
| 405 // Calls are translated to direct style. | 394 // Calls are translated to direct style. |
| 406 List<Expression> arguments = translateArguments(node.arguments); | 395 List<Expression> arguments = translateArguments(node.arguments); |
| 407 Expression invoke = new InvokeStatic(node.target, node.selector, arguments); | 396 Expression invoke = new InvokeStatic(node.target, node.selector, arguments); |
| 408 return continueWithExpression(node.continuation, invoke); | 397 return continueWithExpression(node.continuation, invoke); |
| 409 } | 398 } |
| 410 | 399 |
| 411 Statement visitInvokeMethod(cps_ir.InvokeMethod node) { | 400 Statement visitInvokeMethod(cps_ir.InvokeMethod node) { |
| 412 Expression invoke = new InvokeMethod(getVariableReference(node.receiver), | 401 Expression invoke = new InvokeMethod(getVariableUse(node.receiver), |
| 413 node.selector, | 402 node.selector, |
| 414 translateArguments(node.arguments)); | 403 translateArguments(node.arguments)); |
| 415 return continueWithExpression(node.continuation, invoke); | 404 return continueWithExpression(node.continuation, invoke); |
| 416 } | 405 } |
| 417 | 406 |
| 418 Statement visitInvokeMethodDirectly(cps_ir.InvokeMethodDirectly node) { | 407 Statement visitInvokeMethodDirectly(cps_ir.InvokeMethodDirectly node) { |
| 419 Expression receiver = getVariableReference(node.receiver); | 408 Expression receiver = getVariableUse(node.receiver); |
| 420 List<Expression> arguments = translateArguments(node.arguments); | 409 List<Expression> arguments = translateArguments(node.arguments); |
| 421 Expression invoke = new InvokeMethodDirectly(receiver, node.target, | 410 Expression invoke = new InvokeMethodDirectly(receiver, node.target, |
| 422 node.selector, arguments); | 411 node.selector, arguments); |
| 423 return continueWithExpression(node.continuation, invoke); | 412 return continueWithExpression(node.continuation, invoke); |
| 424 } | 413 } |
| 425 | 414 |
| 426 Statement visitConcatenateStrings(cps_ir.ConcatenateStrings node) { | 415 Statement visitConcatenateStrings(cps_ir.ConcatenateStrings node) { |
| 427 List<Expression> arguments = translateArguments(node.arguments); | 416 List<Expression> arguments = translateArguments(node.arguments); |
| 428 Expression concat = new ConcatenateStrings(arguments); | 417 Expression concat = new ConcatenateStrings(arguments); |
| 429 return continueWithExpression(node.continuation, concat); | 418 return continueWithExpression(node.continuation, concat); |
| 430 } | 419 } |
| 431 | 420 |
| 432 Statement continueWithExpression(cps_ir.Reference continuation, | 421 Statement continueWithExpression(cps_ir.Reference continuation, |
| 433 Expression expression) { | 422 Expression expression) { |
| 434 cps_ir.Continuation cont = continuation.definition; | 423 cps_ir.Continuation cont = continuation.definition; |
| 435 if (cont == returnContinuation) { | 424 if (cont == returnContinuation) { |
| 436 return new Return(expression); | 425 return new Return(expression); |
| 437 } else { | 426 } else { |
| 438 assert(cont.parameters.length == 1); | 427 assert(cont.parameters.length == 1); |
| 439 Function nextBuilder = cont.hasExactlyOneUse ? | 428 Function nextBuilder = cont.hasExactlyOneUse ? |
| 440 () => visit(cont.body) : () => new Break(labels[cont]); | 429 () => visit(cont.body) : () => new Break(labels[cont]); |
| 441 return buildContinuationAssignment(cont.parameters.single, expression, | 430 return buildContinuationAssignment(cont.parameters.single, expression, |
| 442 nextBuilder); | 431 nextBuilder); |
| 443 } | 432 } |
| 444 } | 433 } |
| 445 | 434 |
| 446 Statement visitLetMutable(cps_ir.LetMutable node) { | 435 Statement visitLetMutable(cps_ir.LetMutable node) { |
| 447 Variable variable = addMutableVariable(node.variable); | 436 Variable variable = addMutableVariable(node.variable); |
| 448 Expression value = getVariableReference(node.value); | 437 Expression value = getVariableUse(node.value); |
| 449 return new Assign(variable, value, visit(node.body), isDeclaration: true); | 438 return new Assign(variable, value, visit(node.body), isDeclaration: true); |
| 450 } | 439 } |
| 451 | 440 |
| 452 Expression visitGetMutableVariable(cps_ir.GetMutableVariable node) { | 441 Expression visitGetMutableVariable(cps_ir.GetMutableVariable node) { |
| 453 return getMutableVariableReference(node.variable); | 442 return getMutableVariableUse(node.variable); |
| 454 } | 443 } |
| 455 | 444 |
| 456 Statement visitSetMutableVariable(cps_ir.SetMutableVariable node) { | 445 Statement visitSetMutableVariable(cps_ir.SetMutableVariable node) { |
| 457 Variable variable = getMutableVariableReference(node.variable); | 446 Variable variable = getMutableVariable(node.variable.definition); |
| 458 Expression value = getVariableReference(node.value); | 447 Expression value = getVariableUse(node.value); |
| 459 return new Assign(variable, value, visit(node.body)); | 448 return new Assign(variable, value, visit(node.body)); |
| 460 } | 449 } |
| 461 | 450 |
| 462 Statement visitDeclareFunction(cps_ir.DeclareFunction node) { | 451 Statement visitDeclareFunction(cps_ir.DeclareFunction node) { |
| 463 Variable variable = addMutableVariable(node.variable); | 452 Variable variable = addMutableVariable(node.variable); |
| 464 FunctionDefinition function = makeSubFunction(node.definition); | 453 FunctionDefinition function = makeSubFunction(node.definition); |
| 465 return new FunctionDeclaration(variable, function, visit(node.body)); | 454 return new FunctionDeclaration(variable, function, visit(node.body)); |
| 466 } | 455 } |
| 467 | 456 |
| 468 Statement visitTypeOperator(cps_ir.TypeOperator node) { | 457 Statement visitTypeOperator(cps_ir.TypeOperator node) { |
| 469 Expression receiver = getVariableReference(node.receiver); | 458 Expression receiver = getVariableUse(node.receiver); |
| 470 Expression concat = | 459 Expression concat = |
| 471 new TypeOperator(receiver, node.type, isTypeTest: node.isTypeTest); | 460 new TypeOperator(receiver, node.type, isTypeTest: node.isTypeTest); |
| 472 return continueWithExpression(node.continuation, concat); | 461 return continueWithExpression(node.continuation, concat); |
| 473 } | 462 } |
| 474 | 463 |
| 475 Statement visitInvokeConstructor(cps_ir.InvokeConstructor node) { | 464 Statement visitInvokeConstructor(cps_ir.InvokeConstructor node) { |
| 476 List<Expression> arguments = translateArguments(node.arguments); | 465 List<Expression> arguments = translateArguments(node.arguments); |
| 477 Expression invoke = | 466 Expression invoke = |
| 478 new InvokeConstructor(node.type, node.target, node.selector, arguments); | 467 new InvokeConstructor(node.type, node.target, node.selector, arguments); |
| 479 return continueWithExpression(node.continuation, invoke); | 468 return continueWithExpression(node.continuation, invoke); |
| 480 } | 469 } |
| 481 | 470 |
| 482 Statement visitInvokeContinuation(cps_ir.InvokeContinuation node) { | 471 Statement visitInvokeContinuation(cps_ir.InvokeContinuation node) { |
| 483 // Invocations of the return continuation are translated to returns. | 472 // Invocations of the return continuation are translated to returns. |
| 484 // Other continuation invocations are replaced with assignments of the | 473 // Other continuation invocations are replaced with assignments of the |
| 485 // arguments to formal parameter variables, followed by the body if | 474 // arguments to formal parameter variables, followed by the body if |
| 486 // the continuation is singly reference or a break if it is multiply | 475 // the continuation is singly reference or a break if it is multiply |
| 487 // referenced. | 476 // referenced. |
| 488 cps_ir.Continuation cont = node.continuation.definition; | 477 cps_ir.Continuation cont = node.continuation.definition; |
| 489 if (cont == returnContinuation) { | 478 if (cont == returnContinuation) { |
| 490 assert(node.arguments.length == 1); | 479 assert(node.arguments.length == 1); |
| 491 return new Return(getVariableReference(node.arguments.single)); | 480 return new Return(getVariableUse(node.arguments.single)); |
| 492 } else { | 481 } else { |
| 493 List<Expression> arguments = translatePhiArguments(node.arguments); | 482 List<Variable> arguments = translatePhiArguments(node.arguments); |
| 494 return buildPhiAssignments(cont.parameters, arguments, | 483 return buildPhiAssignments(cont.parameters, arguments, |
| 495 () { | 484 () { |
| 496 // Translate invocations of recursive and non-recursive | 485 // Translate invocations of recursive and non-recursive |
| 497 // continuations differently. | 486 // continuations differently. |
| 498 // * Non-recursive continuations | 487 // * Non-recursive continuations |
| 499 // - If there is one use, translate the continuation body | 488 // - If there is one use, translate the continuation body |
| 500 // inline at the invocation site. | 489 // inline at the invocation site. |
| 501 // - If there are multiple uses, translate to Break. | 490 // - If there are multiple uses, translate to Break. |
| 502 // * Recursive continuations | 491 // * Recursive continuations |
| 503 // - There is a single non-recursive invocation. Translate | 492 // - There is a single non-recursive invocation. Translate |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 547 return new LiteralList( | 536 return new LiteralList( |
| 548 node.type, | 537 node.type, |
| 549 translateArguments(node.values)); | 538 translateArguments(node.values)); |
| 550 } | 539 } |
| 551 | 540 |
| 552 Expression visitLiteralMap(cps_ir.LiteralMap node) { | 541 Expression visitLiteralMap(cps_ir.LiteralMap node) { |
| 553 return new LiteralMap( | 542 return new LiteralMap( |
| 554 node.type, | 543 node.type, |
| 555 new List<LiteralMapEntry>.generate(node.entries.length, (int index) { | 544 new List<LiteralMapEntry>.generate(node.entries.length, (int index) { |
| 556 return new LiteralMapEntry( | 545 return new LiteralMapEntry( |
| 557 getVariableReference(node.entries[index].key), | 546 getVariableUse(node.entries[index].key), |
| 558 getVariableReference(node.entries[index].value)); | 547 getVariableUse(node.entries[index].value)); |
| 559 }) | 548 }) |
| 560 ); | 549 ); |
| 561 } | 550 } |
| 562 | 551 |
| 563 FunctionDefinition makeSubFunction(cps_ir.FunctionDefinition function) { | 552 FunctionDefinition makeSubFunction(cps_ir.FunctionDefinition function) { |
| 564 return createInnerBuilder().buildFunction(function); | 553 return createInnerBuilder().buildFunction(function); |
| 565 } | 554 } |
| 566 | 555 |
| 567 Node visitCreateFunction(cps_ir.CreateFunction node) { | 556 Node visitCreateFunction(cps_ir.CreateFunction node) { |
| 568 FunctionDefinition def = makeSubFunction(node.definition); | 557 FunctionDefinition def = makeSubFunction(node.definition); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 585 } | 574 } |
| 586 | 575 |
| 587 Expression visitContinuation(cps_ir.Continuation node) { | 576 Expression visitContinuation(cps_ir.Continuation node) { |
| 588 // Until continuations with multiple uses are supported, they are not | 577 // Until continuations with multiple uses are supported, they are not |
| 589 // visited. | 578 // visited. |
| 590 internalError(CURRENT_ELEMENT_SPANNABLE, 'Unexpected IR node: $node.'); | 579 internalError(CURRENT_ELEMENT_SPANNABLE, 'Unexpected IR node: $node.'); |
| 591 return null; | 580 return null; |
| 592 } | 581 } |
| 593 | 582 |
| 594 Expression visitIsTrue(cps_ir.IsTrue node) { | 583 Expression visitIsTrue(cps_ir.IsTrue node) { |
| 595 return getVariableReference(node.value); | 584 return getVariableUse(node.value); |
| 596 } | 585 } |
| 597 } | 586 } |
| 598 | 587 |
| OLD | NEW |