Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(318)

Side by Side Diff: lib/compiler/implementation/ssa/codegen.dart

Issue 10669035: Don't lose the expected precedence during && compilation. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Protect non-assignments in define. Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | tests/language/if_and_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, 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 class SsaCodeGeneratorTask extends CompilerTask { 5 class SsaCodeGeneratorTask extends CompilerTask {
6 final JavaScriptBackend backend; 6 final JavaScriptBackend backend;
7 SsaCodeGeneratorTask(JavaScriptBackend backend) 7 SsaCodeGeneratorTask(JavaScriptBackend backend)
8 : this.backend = backend, 8 : this.backend = backend,
9 super(backend.compiler); 9 super(backend.compiler);
10 String get name() => 'SSA code generator'; 10 String get name() => 'SSA code generator';
(...skipping 375 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 } 386 }
387 generationState = oldState; 387 generationState = oldState;
388 } 388 }
389 389
390 /** 390 /**
391 * Generate expressions from block information. 391 * Generate expressions from block information.
392 */ 392 */
393 void generateExpression(HExpressionInformation expression) { 393 void generateExpression(HExpressionInformation expression) {
394 // Currently we only handle sub-expression graphs. 394 // Currently we only handle sub-expression graphs.
395 assert(expression is HSubExpressionBlockInformation); 395 assert(expression is HSubExpressionBlockInformation);
396 // [visitSubGraph] will reset the [expectedPrecedence]. Make sure we don't
397 // need parenthesis.
Lasse Reichstein Nielsen 2012/06/27 08:53:58 I.e., this only expects to be called for top-level
floitsch 2012/06/27 11:18:24 Done.
398 assert(expectedPrecedence == JSPrecedence.STATEMENT_PRECEDENCE
399 || expectedPrecedence == JSPrecedence.EXPRESSION_PRECEDENCE);
400
396 HSubExpressionBlockInformation expressionSubGraph = expression; 401 HSubExpressionBlockInformation expressionSubGraph = expression;
397 402
398 int oldState = generationState; 403 int oldState = generationState;
399 generationState = STATE_FIRST_EXPRESSION; 404 generationState = STATE_FIRST_EXPRESSION;
400 visitSubGraph(expressionSubGraph.subExpression); 405 visitSubGraph(expressionSubGraph.subExpression);
401 generationState = oldState; 406 generationState = oldState;
402 } 407 }
403 408
404 void generateDeclaration(HExpressionInformation expression) { 409 void generateDeclaration(HExpressionInformation expression) {
405 // Currently we only handle sub-expression graphs. 410 // Currently we only handle sub-expression graphs.
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 String inputName = variableNames.getName(instruction.checkedInput); 569 String inputName = variableNames.getName(instruction.checkedInput);
565 if (name != inputName) return false; 570 if (name != inputName) return false;
566 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); 571 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE);
567 return true; 572 return true;
568 } 573 }
569 574
570 void define(HInstruction instruction) { 575 void define(HInstruction instruction) {
571 if (isGeneratingExpression()) { 576 if (isGeneratingExpression()) {
572 addExpressionSeparator(); 577 addExpressionSeparator();
573 } else { 578 } else {
579 assert(expectedPrecedence == JSPrecedence.STATEMENT_PRECEDENCE);
574 addIndentation(); 580 addIndentation();
575 } 581 }
576 if (!instruction.isControlFlow() && variableNames.hasName(instruction)) { 582 if (!instruction.isControlFlow() && variableNames.hasName(instruction)) {
577 var name = variableNames.getName(instruction); 583 var name = variableNames.getName(instruction);
578 if (!handleSimpleUpdateDefinition(instruction, name) 584 if (!handleSimpleUpdateDefinition(instruction, name)
579 && !handleTypeConversion(instruction, name)) { 585 && !handleTypeConversion(instruction, name)) {
580 declareInstruction(instruction); 586 withPrecedence(JSPrecedence.ASSIGNMENT_PRECEDENCE, () {
581 buffer.add(" = "); 587 declareInstruction(instruction);
582 visit(instruction, JSPrecedence.ASSIGNMENT_PRECEDENCE); 588 buffer.add(" = ");
589 visit(instruction, JSPrecedence.ASSIGNMENT_PRECEDENCE);
590 });
583 } 591 }
584 } else { 592 } else {
585 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); 593 visit(instruction, expectedPrecedence);
586 } 594 }
587 if (!isGeneratingExpression()) buffer.add(';\n'); 595 if (!isGeneratingExpression()) buffer.add(';\n');
588 } 596 }
589 597
590 void use(HInstruction argument, int expectedPrecedenceForArgument) { 598 void use(HInstruction argument, int expectedPrecedenceForArgument) {
591 if (isGenerateAtUseSite(argument)) { 599 if (isGenerateAtUseSite(argument)) {
592 visit(argument, expectedPrecedenceForArgument); 600 visit(argument, expectedPrecedenceForArgument);
593 } else if (argument is HCheck && argument.isControlFlow()) { 601 } else if (argument is HCheck && argument.isControlFlow()) {
594 // A [HCheck] that has control flow can never be used as an 602 // A [HCheck] that has control flow can never be used as an
595 // expression and may not have a name. Therefore we just use the 603 // expression and may not have a name. Therefore we just use the
(...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after
1104 } 1112 }
1105 } 1113 }
1106 } 1114 }
1107 1115
1108 void iterateBasicBlock(HBasicBlock node) { 1116 void iterateBasicBlock(HBasicBlock node) {
1109 HInstruction instruction = node.first; 1117 HInstruction instruction = node.first;
1110 while (instruction !== node.last) { 1118 while (instruction !== node.last) {
1111 if (instruction is HTypeGuard) { 1119 if (instruction is HTypeGuard) {
1112 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); 1120 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE);
1113 } else if (!isGenerateAtUseSite(instruction)) { 1121 } else if (!isGenerateAtUseSite(instruction)) {
1122 expectedPrecedence = JSPrecedence.STATEMENT_PRECEDENCE;
1114 define(instruction); 1123 define(instruction);
Lasse Reichstein Nielsen 2012/06/27 08:53:58 Won't a "define" always expect to be at the "state
floitsch 2012/06/27 11:18:24 No. 'define' is called from visitExpression below.
1115 } 1124 }
1116 instruction = instruction.next; 1125 instruction = instruction.next;
1117 } 1126 }
1118 assignPhisOfSuccessors(node); 1127 assignPhisOfSuccessors(node);
1119 if (instruction is HLoopBranch && isGeneratingExpression()) { 1128 if (instruction is HLoopBranch && isGeneratingExpression()) {
1120 addExpressionSeparator(); 1129 addExpressionSeparator();
1121 } 1130 }
1122 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE); 1131 visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE);
1123 } 1132 }
1124 1133
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
1450 int thenKind = analyzeGraphForCodegen(thenGraph); 1459 int thenKind = analyzeGraphForCodegen(thenGraph);
1451 int elseKind = analyzeGraphForCodegen(elseGraph); 1460 int elseKind = analyzeGraphForCodegen(elseGraph);
1452 1461
1453 void visitWithoutIndent(HStatementInformation toVisit) { 1462 void visitWithoutIndent(HStatementInformation toVisit) {
1454 int oldIndent = indent; 1463 int oldIndent = indent;
1455 indent = 0; 1464 indent = 0;
1456 generateStatements(toVisit); 1465 generateStatements(toVisit);
1457 indent = oldIndent; 1466 indent = oldIndent;
1458 } 1467 }
1459 1468
1469 void visitExpression(HStatementInformation toVisit) {
1470 // [generateExpression] only works if the [expectedPrecedence] is a
1471 // statement or an expression. We therefore have to duplicate some
1472 // work here.
Lasse Reichstein Nielsen 2012/06/27 08:53:58 Have you considered making a visitSubGraph that ta
floitsch 2012/06/27 11:18:24 Without the asserts we only have 8 lines here. The
1473 assert(toVisit.start == toVisit.end);
1474 assert(toVisit.start.last is HGoto);
1475 // Find the expression (there must only be one).
1476 HInstruction expression = toVisit.start.first;
1477 while (generateAtUseSite.contains(expression)) {
1478 expression = expression.next;
1479 }
1480 assert(() {
1481 HInstruction remaining = expression.next;
1482 while (remaining is !HGoto) {
1483 if (generateAtUseSite.contains(remaining)) return false;
Lasse Reichstein Nielsen 2012/06/27 08:53:58 Shouldn't this test be negated?
floitsch 2012/06/27 11:18:24 Done.
1484 remaining = remaining.next;
1485 }
1486 return true;
1487 });
1488
1489 int oldState = generationState;
1490 generationState = STATE_FIRST_EXPRESSION;
Lasse Reichstein Nielsen 2012/06/27 08:53:58 x
floitsch 2012/06/27 11:18:24 Done.
1491 define(expression);
1492 generationState = oldState;
1493 }
1494
1460 void visitWithIndent(HStatementInformation toVisit) { 1495 void visitWithIndent(HStatementInformation toVisit) {
1461 buffer.add('{\n'); 1496 buffer.add('{\n');
1462 indent++; 1497 indent++;
1463 generateStatements(toVisit); 1498 generateStatements(toVisit);
1464 indent--; 1499 indent--;
1465 addIndented('}'); 1500 addIndented('}');
1466 } 1501 }
1467 1502
1468 void emitIf() { 1503 void emitIf() {
1469 addIndented('if ('); 1504 addIndented('if (');
1470 use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE); 1505 use(node.inputs[0], JSPrecedence.EXPRESSION_PRECEDENCE);
1471 buffer.add(') '); 1506 buffer.add(') ');
1472 } 1507 }
1473 1508
1474 JSBinaryOperatorPrecedence operatorPrecedence = JSPrecedence.binary['&&']; 1509 JSBinaryOperatorPrecedence operatorPrecedence = JSPrecedence.binary['&&'];
1475 void generateAnd(HStatementInformation toVisit, Function condition) { 1510 void generateAnd(HStatementInformation toVisit, Function condition) {
1476 addIndentation(); 1511 addIndentation();
1477 beginExpression(operatorPrecedence.precedence); 1512 beginExpression(operatorPrecedence.precedence);
1478 condition(); 1513 condition();
Lasse Reichstein Nielsen 2012/06/27 08:53:58 Shouldn't this be executed in a scope where expect
floitsch 2012/06/27 11:18:24 Done.
1479 buffer.add(" && "); 1514 buffer.add(" && ");
1480 var oldPrecedence = expectedPrecedence; 1515 var oldPrecedence = expectedPrecedence;
1481 expectedPrecedence = operatorPrecedence.right; 1516 expectedPrecedence = operatorPrecedence.right;
1482 visitWithoutIndent(toVisit); 1517 visitExpression(toVisit);
1483 expectedPrecedence = oldPrecedence; 1518 expectedPrecedence = oldPrecedence;
1484 endExpression(operatorPrecedence.precedence); 1519 endExpression(operatorPrecedence.precedence);
1520 buffer.add(";\n");
1485 } 1521 }
1486 1522
1487 List<HBasicBlock> thenSuccessors = thenGraph.end.successors; 1523 List<HBasicBlock> thenSuccessors = thenGraph.end.successors;
1488 bool thenGraphHasSuccessor = thenSuccessors.length != 0 1524 bool thenGraphHasSuccessor = thenSuccessors.length != 0
1489 && thenSuccessors[0] !== currentGraph.exit; 1525 && thenSuccessors[0] !== currentGraph.exit;
1490 1526
1491 switch (thenKind) { 1527 switch (thenKind) {
1492 case EMPTY: 1528 case EMPTY:
1493 switch (elseKind) { 1529 switch (elseKind) {
1494 case EMPTY: 1530 case EMPTY:
(...skipping 1507 matching lines...) Expand 10 before | Expand all | Expand 10 after
3002 startBailoutSwitch(); 3038 startBailoutSwitch();
3003 } 3039 }
3004 } 3040 }
3005 3041
3006 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) { 3042 void endLabeledBlock(HLabeledBlockInformation labeledBlockInfo) {
3007 if (labeledBlockInfo.body.start.hasGuards()) { 3043 if (labeledBlockInfo.body.start.hasGuards()) {
3008 endBailoutSwitch(); 3044 endBailoutSwitch();
3009 } 3045 }
3010 } 3046 }
3011 } 3047 }
OLDNEW
« no previous file with comments | « no previous file | tests/language/if_and_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698