Don't lose the expected precedence during && compilation.

When transforming if (foo) bar; to foo && bar make sure that
bar is compiled with the correct precedence.
In particular avoid foo && toto = 499;
instead of
foo && (toto = 499).

Fixes issue 3862.

Review URL: https://chromiumcodereview.appspot.com//10669035

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@9157 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
floitsch@google.com
2012-06-27 11:40:55 +00:00
parent 2096714de0
commit 232fbebdfa
2 changed files with 75 additions and 6 deletions
+44 -6
View File
@@ -393,6 +393,12 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
void generateExpression(HExpressionInformation expression) {
// Currently we only handle sub-expression graphs.
assert(expression is HSubExpressionBlockInformation);
// [visitSubGraph] will reset the [expectedPrecedence]. Make sure we don't
// need parenthesis. I.e., this only expects to be called for top-level
// expressions, not sub-expressions.
assert(expectedPrecedence == JSPrecedence.STATEMENT_PRECEDENCE
|| expectedPrecedence == JSPrecedence.EXPRESSION_PRECEDENCE);
HSubExpressionBlockInformation expressionSubGraph = expression;
int oldState = generationState;
@@ -571,18 +577,21 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
if (isGeneratingExpression()) {
addExpressionSeparator();
} else {
assert(expectedPrecedence == JSPrecedence.STATEMENT_PRECEDENCE);
addIndentation();
}
if (!instruction.isControlFlow() && variableNames.hasName(instruction)) {
var name = variableNames.getName(instruction);
if (!handleSimpleUpdateDefinition(instruction, name)
&& !handleTypeConversion(instruction, name)) {
declareInstruction(instruction);
buffer.add(" = ");
visit(instruction, JSPrecedence.ASSIGNMENT_PRECEDENCE);
withPrecedence(JSPrecedence.ASSIGNMENT_PRECEDENCE, () {
declareInstruction(instruction);
buffer.add(" = ");
visit(instruction, JSPrecedence.ASSIGNMENT_PRECEDENCE);
});
}
} else {
visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE);
visit(instruction, expectedPrecedence);
}
if (!isGeneratingExpression()) buffer.add(';\n');
}
@@ -1111,6 +1120,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
if (instruction is HTypeGuard) {
visit(instruction, JSPrecedence.STATEMENT_PRECEDENCE);
} else if (!isGenerateAtUseSite(instruction)) {
expectedPrecedence = JSPrecedence.STATEMENT_PRECEDENCE;
define(instruction);
}
instruction = instruction.next;
@@ -1457,6 +1467,32 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
indent = oldIndent;
}
void visitExpression(HStatementInformation toVisit) {
// [generateExpression] only works if the [expectedPrecedence] is a
// statement or an expression. We therefore have to duplicate some
// work here.
assert(toVisit.start == toVisit.end);
assert(toVisit.start.last is HGoto);
// Find the expression (there must only be one).
HInstruction expression = toVisit.start.first;
while (generateAtUseSite.contains(expression)) {
expression = expression.next;
}
assert(() {
HInstruction remaining = expression.next;
while (remaining is !HGoto) {
if (!generateAtUseSite.contains(remaining)) return false;
remaining = remaining.next;
}
return true;
});
int oldState = generationState;
generationState = STATE_FIRST_EXPRESSION;
define(expression);
generationState = oldState;
}
void visitWithIndent(HStatementInformation toVisit) {
buffer.add('{\n');
indent++;
@@ -1475,13 +1511,15 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
void generateAnd(HStatementInformation toVisit, Function condition) {
addIndentation();
beginExpression(operatorPrecedence.precedence);
var oldPrecedence = expectedPrecedence;
expectedPrecedence = operatorPrecedence.left;
condition();
buffer.add(" && ");
var oldPrecedence = expectedPrecedence;
expectedPrecedence = operatorPrecedence.right;
visitWithoutIndent(toVisit);
visitExpression(toVisit);
expectedPrecedence = oldPrecedence;
endExpression(operatorPrecedence.precedence);
buffer.add(";\n");
}
List<HBasicBlock> thenSuccessors = thenGraph.end.successors;
+31
View File
@@ -0,0 +1,31 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// The "if (negative) res2 |= 3" below can be emitted as negative && (res2 |= 3)
// in JavaScript. Dart2js produced the wrong output.
_shiftRight(x, y) => x;
int64_bits(x) => x;
class A {
opshr(int n, a2) {
int res2;
bool negative = a2 === 496;
res2 = _shiftRight(a2, n);
if (negative) {
res2 |= 3;
}
return int64_bits(res2);
}
}
main() {
var a = new A();
var t;
for (int i = 0; i < 3; i++) {
t = a.opshr(99, 496);
}
Expect.equals(499, t);
}