Ensure that basic blocks are terminated.
authorRoberto Raggi <roberto.raggi@nokia.com>
Fri, 8 Jun 2012 11:29:21 +0000 (13:29 +0200)
committerRoberto Raggi <roberto.raggi@nokia.com>
Fri, 8 Jun 2012 11:53:18 +0000 (13:53 +0200)
Also make sure that the special BasicBlock `exitBlock' is always
the last block of the function.

qv4codegen.cpp
qv4ir.cpp
qv4ir_p.h

index b67c52f..3e0a9e4 100644 (file)
@@ -1282,10 +1282,9 @@ bool Codegen::visit(FunctionDeclaration *ast)
 
 void Codegen::linearize(IR::Function *function)
 {
-    IR::BasicBlock *entryBlock = function->basicBlocks.at(0);
-    IR::BasicBlock *exitBlock = function->basicBlocks.at(1);
-
-    Q_UNUSED(entryBlock);
+    IR::BasicBlock *exitBlock = function->basicBlocks.last();
+    assert(exitBlock->isTerminated());
+    assert(exitBlock->terminator()->asRet());
 
     QSet<IR::BasicBlock *> V;
     V.insert(exitBlock);
@@ -1294,11 +1293,9 @@ void Codegen::linearize(IR::Function *function)
 
     for (int i = 0; i < function->basicBlocks.size(); ++i) {
         IR::BasicBlock *block = function->basicBlocks.at(i);
-        if (block->statements.isEmpty()) {
-            if ((i + 1) < function->basicBlocks.size()) {
-                IR::BasicBlock *next = function->basicBlocks.at(i + 1);
-                block->JUMP(next);
-            }
+        if (!block->isTerminated() && (i + 1) < function->basicBlocks.size()) {
+            IR::BasicBlock *next = function->basicBlocks.at(i + 1);
+            block->JUMP(next);
         }
     }
 
@@ -1440,7 +1437,7 @@ IR::Function *Codegen::defineFunction(const QString &name, AST::Node *ast,
     enterEnvironment(ast);
     IR::Function *function = _module->newFunction(name);
     IR::BasicBlock *entryBlock = function->newBasicBlock();
-    IR::BasicBlock *exitBlock = function->newBasicBlock();
+    IR::BasicBlock *exitBlock = function->newBasicBlock(IR::Function::DontInsertBlock);
     IR::BasicBlock *throwBlock = function->newBasicBlock();
     IR::BasicBlock *handlersBlock = function->newBasicBlock();
     function->hasDirectEval = _env->hasDirectEval;
@@ -1478,6 +1475,8 @@ IR::Function *Codegen::defineFunction(const QString &name, AST::Node *ast,
 
     sourceElements(body);
 
+    _function->insertBasicBlock(_exitBlock);
+
     if (! _block->isTerminated())
         _block->JUMP(_exitBlock);
 
index 5f85134..f27d318 100644 (file)
--- a/qv4ir.cpp
+++ b/qv4ir.cpp
@@ -493,9 +493,10 @@ const QString *Function::newString(const QString &text)
     return &*strings.insert(text);
 }
 
-BasicBlock *Function::newBasicBlock()
+BasicBlock *Function::newBasicBlock(BasicBlockInsertMode mode)
 {
-    return i(new BasicBlock(this));
+    BasicBlock *block = new BasicBlock(this);
+    return mode == InsertBlock ? insertBasicBlock(block) : block;
 }
 
 void Function::dump(QTextStream &out, Stmt::Mode mode)
index 95cc28d..f6467c9 100644 (file)
--- a/qv4ir_p.h
+++ b/qv4ir_p.h
@@ -624,13 +624,18 @@ struct Function {
 
     ~Function();
 
-    BasicBlock *newBasicBlock();
+    enum BasicBlockInsertMode {
+        InsertBlock,
+        DontInsertBlock
+    };
+
+    BasicBlock *newBasicBlock(BasicBlockInsertMode mode = InsertBlock);
     const QString *newString(const QString &text);
 
     void RECEIVE(const QString &name) { formals.append(newString(name)); }
     void LOCAL(const QString &name) { locals.append(newString(name)); }
 
-    inline BasicBlock *i(BasicBlock *block) { basicBlocks.append(block); return block; }
+    inline BasicBlock *insertBasicBlock(BasicBlock *block) { basicBlocks.append(block); return block; }
 
     void dump(QTextStream &out, Stmt::Mode mode = Stmt::HIR);