Generate nested else if:

if (a) {
} else if () {
}

instead of:

if (a) {
} else {
  if () {
  }
}
Review URL: https://chromiumcodereview.appspot.com//10541173

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@8800 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
ngeoffray@google.com
2012-06-18 15:55:25 +00:00
parent 4e72987380
commit 5afea1070a
+58 -16
View File
@@ -123,7 +123,8 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
static final int ONE_STATEMENT = 0;
static final int ONE_EXPRESSION = 1;
static final int EMPTY = 2;
static final int MULTIPLE_STATEMENTS = 3;
static final int IF_STATEMENT = 3;
static final int MULTIPLE_STATEMENTS = 4;
/**
* Returned by [expressionType] to tell how code can be generated for
@@ -175,11 +176,19 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
int expectedPrecedence = JSPrecedence.STATEMENT_PRECEDENCE;
JSBinaryOperatorPrecedence unsignedShiftPrecedences;
HGraph currentGraph;
/**
* Whether the code-generation should try to generate an expression
* instead of a sequence of statements.
*/
int generationState = STATE_STATEMENT;
/**
* Whether we are generating a statement that does not need
* indentation (e.g. an 'if' in an 'else if').
*/
bool generatingInlineStatement = false;
HBasicBlock currentBlock;
// Records a block-information that is being handled specially.
@@ -1328,12 +1337,10 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
* contains one statement, one expression, or multiple statements.
*/
int analyzeGraphForCodegen(HStatementInformation graph) {
HBasicBlock start = graph.start;
HBasicBlock end = graph.end;
// Only deal with single blocks for now. TODO(ngeoffray): analyze
// all blocks.
if (start !== end) return MULTIPLE_STATEMENTS;
return analyzeBlocksForCodegen(graph.start, graph.end);
}
int analyzeBlocksForCodegen(HBasicBlock start, HBasicBlock end) {
int kind = EMPTY;
bool updateKind(int newKind) {
if (kind != EMPTY) return false;
@@ -1352,10 +1359,26 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
}
HInstruction last = start.last;
if (last is !HGoto) {
if (!updateKind(last.isStatement() ? ONE_STATEMENT : ONE_EXPRESSION)) {
if (last is HGoto) {
if (start !== end) {
int nextKind = analyzeBlocksForCodegen(start.successors[0], end);
if (!updateKind(nextKind)) return MULTIPLE_STATEMENTS;
}
} else if (last is HIf) {
HIf ifInstruction = last;
if (ifInstruction.joinBlock !== null
&& analyzeBlocksForCodegen(ifInstruction.joinBlock, end) != EMPTY) {
return MULTIPLE_STATEMENTS;
}
int ifKind = controlFlowOperators.contains(ifInstruction)
? ONE_EXPRESSION
: IF_STATEMENT;
if (!updateKind(ifKind)) return MULTIPLE_STATEMENTS;
} else if (start !== end) {
return MULTIPLE_STATEMENTS;
} else if (!updateKind(
last.isStatement() ? ONE_STATEMENT : ONE_EXPRESSION)) {
return MULTIPLE_STATEMENTS;
}
CopyHandler handler = variableNames.getCopyHandler(start);
@@ -1389,6 +1412,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
// Usually, the variable name is longer than 'if' and it takes up
// more space to duplicate the name.
if (!atUseSite
&& !generatingInlineStatement
&& variableNames.getName(phi) == variableNames.getName(phi.inputs[1])) {
return false;
}
@@ -1404,16 +1428,14 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
int elseKind = analyzeGraphForCodegen(elseGraph);
void visitWithoutIndent(HStatementInformation toVisit) {
int oldIndent = indent;
indent = 0;
generateStatements(toVisit);
indent = oldIndent;
generatingInlineStatement = true;
visitSubGraph(new SubGraph(toVisit.start, toVisit.end));
}
void visitWithIndent(HStatementInformation toVisit) {
buffer.add('{\n');
indent++;
generateStatements(toVisit);
visitSubGraph(new SubGraph(toVisit.start, toVisit.end));
indent--;
addIndented('}');
}
@@ -1457,6 +1479,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
break;
case ONE_STATEMENT:
case IF_STATEMENT:
addIndented('if (');
generateNot(node.inputs[0]);
buffer.add(') ');
@@ -1489,6 +1512,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
case ONE_EXPRESSION:
case ONE_STATEMENT:
case IF_STATEMENT:
// TODO(ngeoffray): Generate a conditional.
emitIf();
visitWithoutIndent(thenGraph);
@@ -1515,6 +1539,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
break;
case MULTIPLE_STATEMENTS:
case IF_STATEMENT:
emitIf();
visitWithIndent(thenGraph);
@@ -1525,6 +1550,7 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
case ONE_EXPRESSION:
case ONE_STATEMENT:
case IF_STATEMENT:
if (thenGraphHasSuccessor) {
buffer.add(' else ');
visitWithoutIndent(elseGraph);
@@ -1549,7 +1575,6 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
}
}
visitIf(HIf node) {
if (tryControlFlowOperation(node)) return;
@@ -1567,8 +1592,21 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
HConstant constant = condition;
if (constant.constant.isTrue()) {
generateStatements(info.thenGraph);
int thenKind = analyzeGraphForCodegen(info.thenGraph);
if (thenKind == EMPTY && generatingInlineStatement) {
// If we are generating an inline statement, but that
// statement is actually empty, still emit a ';' (one
// statement) to emit valid syntax (e.g. 'else;').
generatingInlineStatement = false;
buffer.add(';\n');
}
} else {
generateStatements(info.elseGraph);
int elseKind = analyzeGraphForCodegen(info.elseGraph);
if (elseKind == EMPTY && generatingInlineStatement) {
generatingInlineStatement = false;
buffer.add(';\n');
}
}
} else {
generateIf(node, info);
@@ -2029,8 +2067,12 @@ class SsaCodeGenerator implements HVisitor, HBlockInformationVisitor {
}
void addIndentation() {
for (int i = 0; i < indent; i++) {
buffer.add(' ');
if (generatingInlineStatement) {
generatingInlineStatement = false;
} else {
for (int i = 0; i < indent; i++) {
buffer.add(' ');
}
}
}