| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 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 | 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 dart2js.ir_builder; | 5 library dart2js.ir_builder; |
| 6 | 6 |
| 7 import '../constants/expressions.dart'; | 7 import '../constants/expressions.dart'; |
| 8 import '../constants/values.dart' show PrimitiveConstantValue; | 8 import '../constants/values.dart' show PrimitiveConstantValue; |
| 9 import '../dart_backend/dart_backend.dart' show DartBackend; | 9 import '../dart_backend/dart_backend.dart' show DartBackend; |
| 10 import '../dart_types.dart'; | 10 import '../dart_types.dart'; |
| (...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 273 /// | 273 /// |
| 274 /// [isClosureVariable] marks whether [variableElement] is accessed from an | 274 /// [isClosureVariable] marks whether [variableElement] is accessed from an |
| 275 /// inner function. | 275 /// inner function. |
| 276 void declareLocalVariable(LocalVariableElement variableElement, | 276 void declareLocalVariable(LocalVariableElement variableElement, |
| 277 {ir.Primitive initialValue, | 277 {ir.Primitive initialValue, |
| 278 bool isClosureVariable: false}) { | 278 bool isClosureVariable: false}) { |
| 279 assert(isOpen); | 279 assert(isOpen); |
| 280 if (initialValue == null) { | 280 if (initialValue == null) { |
| 281 // TODO(kmillikin): Consider pooling constants. | 281 // TODO(kmillikin): Consider pooling constants. |
| 282 // The initial value is null. | 282 // The initial value is null. |
| 283 initialValue = makePrimConst(state.constantSystem.createNull()); | 283 initialValue = buildNullLiteral(); |
| 284 add(new ir.LetPrim(initialValue)); | |
| 285 } | 284 } |
| 286 if (isClosureVariable) { | 285 if (isClosureVariable) { |
| 287 add(new ir.SetClosureVariable(variableElement, | 286 add(new ir.SetClosureVariable(variableElement, |
| 288 initialValue, | 287 initialValue, |
| 289 isDeclaration: true)); | 288 isDeclaration: true)); |
| 290 } else { | 289 } else { |
| 291 // In case a primitive was introduced for the initializer expression, | 290 // In case a primitive was introduced for the initializer expression, |
| 292 // use this variable element to help derive a good name for it. | 291 // use this variable element to help derive a good name for it. |
| 293 initialValue.useElementAsHint(variableElement); | 292 initialValue.useElementAsHint(variableElement); |
| 294 environment.extend(variableElement, initialValue); | 293 environment.extend(variableElement, initialValue); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 310 } | 309 } |
| 311 | 310 |
| 312 ir.Primitive continueWithExpression(ir.Expression build(ir.Continuation k)) { | 311 ir.Primitive continueWithExpression(ir.Expression build(ir.Continuation k)) { |
| 313 ir.Parameter v = new ir.Parameter(null); | 312 ir.Parameter v = new ir.Parameter(null); |
| 314 ir.Continuation k = new ir.Continuation([v]); | 313 ir.Continuation k = new ir.Continuation([v]); |
| 315 ir.Expression expression = build(k); | 314 ir.Expression expression = build(k); |
| 316 add(new ir.LetCont(k, expression)); | 315 add(new ir.LetCont(k, expression)); |
| 317 return v; | 316 return v; |
| 318 } | 317 } |
| 319 | 318 |
| 320 ir.Constant makeConst(ConstantExpression exp) { | 319 /// Create a constant literal from [constant]. |
| 321 return new ir.Constant(exp); | 320 ir.Constant buildConstantLiteral(ConstantExpression constant) { |
| 322 } | |
| 323 | |
| 324 ir.Constant makePrimConst(PrimitiveConstantValue value) { | |
| 325 return makeConst(new PrimitiveConstantExpression(value)); | |
| 326 } | |
| 327 | |
| 328 // TODO(johnniwinther): Build constants directly through [ConstExp] when these | |
| 329 // are created from analyzer2dart. | |
| 330 ir.Node buildPrimConst(PrimitiveConstantValue constant) { | |
| 331 assert(isOpen); | 321 assert(isOpen); |
| 332 ir.Node prim = makePrimConst(constant); | 322 ir.Constant prim = new ir.Constant(constant); |
| 333 add(new ir.LetPrim(prim)); | 323 add(new ir.LetPrim(prim)); |
| 334 return prim; | 324 return prim; |
| 335 } | 325 } |
| 336 | 326 |
| 327 // Helper for building primitive literals. |
| 328 ir.Constant _buildPrimitiveConstant(PrimitiveConstantValue constant) { |
| 329 return buildConstantLiteral(new PrimitiveConstantExpression(constant)); |
| 330 } |
| 331 |
| 337 /// Create an integer literal. | 332 /// Create an integer literal. |
| 338 ir.Constant buildIntegerLiteral(int value) { | 333 ir.Constant buildIntegerLiteral(int value) { |
| 339 return buildPrimConst(state.constantSystem.createInt(value)); | 334 return _buildPrimitiveConstant(state.constantSystem.createInt(value)); |
| 340 } | 335 } |
| 341 | 336 |
| 342 /// Create an double literal. | 337 /// Create an double literal. |
| 343 ir.Constant buildDoubleLiteral(double value) { | 338 ir.Constant buildDoubleLiteral(double value) { |
| 344 return buildPrimConst(state.constantSystem.createDouble(value)); | 339 return _buildPrimitiveConstant(state.constantSystem.createDouble(value)); |
| 345 } | 340 } |
| 346 | 341 |
| 347 /// Create an bool literal. | 342 /// Create an bool literal. |
| 348 ir.Constant buildBooleanLiteral(bool value) { | 343 ir.Constant buildBooleanLiteral(bool value) { |
| 349 return buildPrimConst(state.constantSystem.createBool(value)); | 344 return _buildPrimitiveConstant(state.constantSystem.createBool(value)); |
| 350 } | 345 } |
| 351 | 346 |
| 352 /// Create an null literal. | 347 /// Create an null literal. |
| 353 ir.Constant buildNullLiteral() { | 348 ir.Constant buildNullLiteral() { |
| 354 return buildPrimConst(state.constantSystem.createNull()); | 349 return _buildPrimitiveConstant(state.constantSystem.createNull()); |
| 355 } | 350 } |
| 356 | 351 |
| 357 /// Create a string literal. | 352 /// Create a string literal. |
| 358 ir.Constant buildStringLiteral(String value) { | 353 ir.Constant buildStringLiteral(String value) { |
| 359 return buildPrimConst( | 354 return _buildPrimitiveConstant( |
| 360 state.constantSystem.createString(new ast.DartString.literal(value))); | 355 state.constantSystem.createString(new ast.DartString.literal(value))); |
| 361 } | 356 } |
| 362 | 357 |
| 363 /// Create a get access of [local]. | 358 /// Create a get access of [local]. |
| 364 ir.Primitive buildLocalGet(Element local) { | 359 ir.Primitive buildLocalGet(Element local) { |
| 365 assert(isOpen); | 360 assert(isOpen); |
| 366 return environment.lookup(local); | 361 return environment.lookup(local); |
| 367 } | 362 } |
| 368 | 363 |
| 369 /// Create a get access of the static [element]. | 364 /// Create a get access of the static [element]. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 385 receiver, selector, k, const <ir.Definition>[])); | 380 receiver, selector, k, const <ir.Definition>[])); |
| 386 } | 381 } |
| 387 | 382 |
| 388 /** | 383 /** |
| 389 * Add an explicit `return null` for functions that don't have a return | 384 * Add an explicit `return null` for functions that don't have a return |
| 390 * statement on each branch. This includes functions with an empty body, | 385 * statement on each branch. This includes functions with an empty body, |
| 391 * such as `foo(){ }`. | 386 * such as `foo(){ }`. |
| 392 */ | 387 */ |
| 393 void ensureReturn() { | 388 void ensureReturn() { |
| 394 if (!isOpen) return; | 389 if (!isOpen) return; |
| 395 ir.Constant constant = makePrimConst(state.constantSystem.createNull()); | 390 ir.Constant constant = buildNullLiteral(); |
| 396 add(new ir.LetPrim(constant)); | |
| 397 add(new ir.InvokeContinuation(state.returnContinuation, [constant])); | 391 add(new ir.InvokeContinuation(state.returnContinuation, [constant])); |
| 398 _current = null; | 392 _current = null; |
| 399 } | 393 } |
| 400 | 394 |
| 401 /// Create a [ir.FunctionDefinition] for [element] using [_root] as the body. | 395 /// Create a [ir.FunctionDefinition] for [element] using [_root] as the body. |
| 402 /// | 396 /// |
| 403 /// Parameters must be created before the construction of the body using | 397 /// Parameters must be created before the construction of the body using |
| 404 /// [createParameter]. | 398 /// [createParameter]. |
| 405 ir.FunctionDefinition buildFunctionDefinition( | 399 ir.FunctionDefinition buildFunctionDefinition( |
| 406 FunctionElement element, | 400 FunctionElement element, |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 454 | 448 |
| 455 /// Create a return statement `return value;` or `return;` if [value] is | 449 /// Create a return statement `return value;` or `return;` if [value] is |
| 456 /// null. | 450 /// null. |
| 457 void buildReturn([ir.Primitive value]) { | 451 void buildReturn([ir.Primitive value]) { |
| 458 // Build(Return(e), C) = C'[InvokeContinuation(return, x)] | 452 // Build(Return(e), C) = C'[InvokeContinuation(return, x)] |
| 459 // where (C', x) = Build(e, C) | 453 // where (C', x) = Build(e, C) |
| 460 // | 454 // |
| 461 // Return without a subexpression is translated as if it were return null. | 455 // Return without a subexpression is translated as if it were return null. |
| 462 assert(isOpen); | 456 assert(isOpen); |
| 463 if (value == null) { | 457 if (value == null) { |
| 464 value = makePrimConst(state.constantSystem.createNull()); | 458 value = buildNullLiteral(); |
| 465 add(new ir.LetPrim(value)); | |
| 466 } | 459 } |
| 467 add(new ir.InvokeContinuation(state.returnContinuation, [value])); | 460 add(new ir.InvokeContinuation(state.returnContinuation, [value])); |
| 468 _current = null; | 461 _current = null; |
| 469 } | 462 } |
| 470 | 463 |
| 471 // Build(BreakStatement L, C) = C[InvokeContinuation(...)] | 464 // Build(BreakStatement L, C) = C[InvokeContinuation(...)] |
| 472 // | 465 // |
| 473 // The continuation and arguments are filled in later after translating | 466 // The continuation and arguments are filled in later after translating |
| 474 // the body containing the break. | 467 // the body containing the break. |
| 475 bool buildBreak(JumpTarget target) { | 468 bool buildBreak(JumpTarget target) { |
| (...skipping 24 matching lines...) Expand all Loading... |
| 500 ir.Primitive buildNegation(ir.Primitive condition) { | 493 ir.Primitive buildNegation(ir.Primitive condition) { |
| 501 // ! e is translated as e ? false : true | 494 // ! e is translated as e ? false : true |
| 502 | 495 |
| 503 // Add a continuation parameter for the result of the expression. | 496 // Add a continuation parameter for the result of the expression. |
| 504 ir.Parameter resultParameter = new ir.Parameter(null); | 497 ir.Parameter resultParameter = new ir.Parameter(null); |
| 505 | 498 |
| 506 ir.Continuation joinContinuation = new ir.Continuation([resultParameter]); | 499 ir.Continuation joinContinuation = new ir.Continuation([resultParameter]); |
| 507 ir.Continuation thenContinuation = new ir.Continuation([]); | 500 ir.Continuation thenContinuation = new ir.Continuation([]); |
| 508 ir.Continuation elseContinuation = new ir.Continuation([]); | 501 ir.Continuation elseContinuation = new ir.Continuation([]); |
| 509 | 502 |
| 510 ir.Constant trueConstant = | 503 ir.Constant makeBoolConstant(bool value) { |
| 511 makePrimConst(state.constantSystem.createBool(true)); | 504 return new ir.Constant(new PrimitiveConstantExpression( |
| 512 ir.Constant falseConstant = | 505 state.constantSystem.createBool(value))); |
| 513 makePrimConst(state.constantSystem.createBool(false)); | 506 } |
| 507 |
| 508 ir.Constant trueConstant = makeBoolConstant(true); |
| 509 ir.Constant falseConstant = makeBoolConstant(false); |
| 514 | 510 |
| 515 thenContinuation.body = new ir.LetPrim(falseConstant) | 511 thenContinuation.body = new ir.LetPrim(falseConstant) |
| 516 ..plug(new ir.InvokeContinuation(joinContinuation, [falseConstant])); | 512 ..plug(new ir.InvokeContinuation(joinContinuation, [falseConstant])); |
| 517 elseContinuation.body = new ir.LetPrim(trueConstant) | 513 elseContinuation.body = new ir.LetPrim(trueConstant) |
| 518 ..plug(new ir.InvokeContinuation(joinContinuation, [trueConstant])); | 514 ..plug(new ir.InvokeContinuation(joinContinuation, [trueConstant])); |
| 519 | 515 |
| 520 add(new ir.LetCont(joinContinuation, | 516 add(new ir.LetCont(joinContinuation, |
| 521 new ir.LetCont(thenContinuation, | 517 new ir.LetCont(thenContinuation, |
| 522 new ir.LetCont(elseContinuation, | 518 new ir.LetCont(elseContinuation, |
| 523 new ir.Branch(new ir.IsTrue(condition), | 519 new ir.Branch(new ir.IsTrue(condition), |
| (...skipping 22 matching lines...) Expand all Loading... |
| 546 // appropriate constant and an invocation of the join-point continuation. | 542 // appropriate constant and an invocation of the join-point continuation. |
| 547 IrBuilder emptyBuilder = new IrBuilder.delimited(this); | 543 IrBuilder emptyBuilder = new IrBuilder.delimited(this); |
| 548 // Dummy empty targets for right true and right false. They hold | 544 // Dummy empty targets for right true and right false. They hold |
| 549 // definitions of the appropriate constant and an invocation of the | 545 // definitions of the appropriate constant and an invocation of the |
| 550 // join-point continuation. | 546 // join-point continuation. |
| 551 IrBuilder rightTrueBuilder = new IrBuilder.delimited(rightBuilder); | 547 IrBuilder rightTrueBuilder = new IrBuilder.delimited(rightBuilder); |
| 552 IrBuilder rightFalseBuilder = new IrBuilder.delimited(rightBuilder); | 548 IrBuilder rightFalseBuilder = new IrBuilder.delimited(rightBuilder); |
| 553 | 549 |
| 554 // If we don't evaluate the right subexpression, the value of the whole | 550 // If we don't evaluate the right subexpression, the value of the whole |
| 555 // expression is this constant. | 551 // expression is this constant. |
| 556 ir.Constant leftBool = emptyBuilder.makePrimConst( | 552 ir.Constant leftBool = emptyBuilder.buildBooleanLiteral(isLazyOr); |
| 557 emptyBuilder.state.constantSystem.createBool(isLazyOr)); | |
| 558 // If we do evaluate the right subexpression, the value of the expression | 553 // If we do evaluate the right subexpression, the value of the expression |
| 559 // is a true or false constant. | 554 // is a true or false constant. |
| 560 ir.Constant rightTrue = rightTrueBuilder.makePrimConst( | 555 ir.Constant rightTrue = rightTrueBuilder.buildBooleanLiteral(true); |
| 561 rightTrueBuilder.state.constantSystem.createBool(true)); | 556 ir.Constant rightFalse = rightFalseBuilder.buildBooleanLiteral(false); |
| 562 ir.Constant rightFalse = rightFalseBuilder.makePrimConst( | |
| 563 rightFalseBuilder.state.constantSystem.createBool(false)); | |
| 564 emptyBuilder.add(new ir.LetPrim(leftBool)); | |
| 565 rightTrueBuilder.add(new ir.LetPrim(rightTrue)); | |
| 566 rightFalseBuilder.add(new ir.LetPrim(rightFalse)); | |
| 567 | 557 |
| 568 // Treat the result values as named values in the environment, so they | 558 // Treat the result values as named values in the environment, so they |
| 569 // will be treated as arguments to the join-point continuation. | 559 // will be treated as arguments to the join-point continuation. |
| 570 assert(environment.length == emptyBuilder.environment.length); | 560 assert(environment.length == emptyBuilder.environment.length); |
| 571 assert(environment.length == rightTrueBuilder.environment.length); | 561 assert(environment.length == rightTrueBuilder.environment.length); |
| 572 assert(environment.length == rightFalseBuilder.environment.length); | 562 assert(environment.length == rightFalseBuilder.environment.length); |
| 573 emptyBuilder.environment.extend(null, leftBool); | 563 emptyBuilder.environment.extend(null, leftBool); |
| 574 rightTrueBuilder.environment.extend(null, rightTrue); | 564 rightTrueBuilder.environment.extend(null, rightTrue); |
| 575 rightFalseBuilder.environment.extend(null, rightFalse); | 565 rightFalseBuilder.environment.extend(null, rightFalse); |
| 576 | 566 |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 715 index = 0; | 705 index = 0; |
| 716 for (int i = 0; i < environment.length; ++i) { | 706 for (int i = 0; i < environment.length; ++i) { |
| 717 if (common[i] == null) { | 707 if (common[i] == null) { |
| 718 environment.index2value[i] = parameters[index++]; | 708 environment.index2value[i] = parameters[index++]; |
| 719 } | 709 } |
| 720 } | 710 } |
| 721 | 711 |
| 722 return join; | 712 return join; |
| 723 } | 713 } |
| 724 } | 714 } |
| OLD | NEW |