From 5afea1070a79ca367151dbfdff1d5344e67352fa Mon Sep 17 00:00:00 2001 From: "ngeoffray@google.com" Date: Mon, 18 Jun 2012 15:55:25 +0000 Subject: [PATCH] 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 --- lib/compiler/implementation/ssa/codegen.dart | 74 +++++++++++++++----- 1 file changed, 58 insertions(+), 16 deletions(-) diff --git a/lib/compiler/implementation/ssa/codegen.dart b/lib/compiler/implementation/ssa/codegen.dart index e513630e77c..add8da3fa64 100644 --- a/lib/compiler/implementation/ssa/codegen.dart +++ b/lib/compiler/implementation/ssa/codegen.dart @@ -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(' '); + } } }