Add the unconditional branch instruction, improve diagnostics for block
references.

PiperOrigin-RevId: 201872745
diff --git a/lib/Parser/Parser.cpp b/lib/Parser/Parser.cpp
index d5cc707..828a8d5 100644
--- a/lib/Parser/Parser.cpp
+++ b/lib/Parser/Parser.cpp
@@ -119,6 +119,9 @@
   ParseResult parseExtFunc();
   ParseResult parseCFGFunc();
   ParseResult parseBasicBlock(CFGFunctionParserState &functionState);
+  TerminatorInst *parseTerminator(BasicBlock *currentBB,
+                                  CFGFunctionParserState &functionState);
+
 };
 } // end anonymous namespace
 
@@ -513,23 +516,22 @@
 /// forward references.
 class CFGFunctionParserState {
 public:
+  CFGFunction *function;
+  llvm::StringMap<std::pair<BasicBlock*, SMLoc>> blocksByName;
+
   CFGFunctionParserState(CFGFunction *function) : function(function) {}
 
   /// Get the basic block with the specified name, creating it if it doesn't
-  /// already exist.
-  BasicBlock *getBlockNamed(StringRef name) {
-    auto *&block = blocksByName[name];
-    if (!block) {
-      block = new BasicBlock(function);
-      // TODO: Should be automatic when we have the right function
-      // representation.
-      function->blockList.push_back(block);
+  /// already exist.  The location specified is the point of use, which allows
+  /// us to diagnose references to blocks that are not defined precisely.
+  BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
+    auto &blockAndLoc = blocksByName[name];
+    if (!blockAndLoc.first) {
+      blockAndLoc.first = new BasicBlock(function);
+      blockAndLoc.second = loc;
     }
-    return block;
+    return blockAndLoc.first;
   }
-private:
-  CFGFunction *function;
-  llvm::StringMap<BasicBlock*> blocksByName;
 };
 } // end anonymous namespace
 
@@ -563,6 +565,16 @@
     if (parseBasicBlock(functionState))
       return ParseFailure;
 
+  // Verify that all referenced blocks were defined.  Iteration over a
+  // StringMap isn't determinstic, but this is good enough for our purposes.
+  for (auto &elt : functionState.blocksByName) {
+    auto *bb = elt.second.first;
+    if (!bb->getTerminator())
+      return emitError(elt.second.second,
+                       "reference to an undefined basic block '" +
+                       elt.first() + "'");
+  }
+
   module->functionList.push_back(function);
   return ParseSuccess;
 }
@@ -579,13 +591,25 @@
   auto name = curToken.getSpelling();
   if (!consumeIf(Token::bare_identifier))
     return emitError("expected basic block name");
-  auto block = functionState.getBlockNamed(name);
+
+  auto block = functionState.getBlockNamed(name, nameLoc);
 
   // If this block has already been parsed, then this is a redefinition with the
   // same block name.
   if (block->getTerminator())
-    return emitError(nameLoc, "redefinition of block named '" +
-                     name.str() + "'");
+    return emitError(nameLoc, "redefinition of block '" + name.str() + "'");
+
+  // References to blocks can occur in any order, but we need to reassemble the
+  // function in the order that occurs in the source file.  Do this by moving
+  // each block to the end of the list as it is defined.
+  // FIXME: This is inefficient for large functions given that blockList is a
+  // vector.  blockList will eventually be an ilist, which will make this fast.
+  auto &blockList = functionState.function->blockList;
+  if (blockList.back() != block) {
+    auto it = std::find(blockList.begin(), blockList.end(), block);
+    assert(it != blockList.end() && "Block has to be in the blockList");
+    std::swap(*it, blockList.back());
+  }
 
   // TODO: parse bb argument list.
 
@@ -602,15 +626,46 @@
   // TODO: parse instruction list.
 
   // TODO: Generalize this once instruction list parsing is built out.
-  if (!consumeIf(Token::kw_return))
-    return emitError("expected 'return' at end of basic block");
 
-  block->setTerminator(new ReturnInst(block));
+  auto *termInst = parseTerminator(block, functionState);
+  if (!termInst)
+    return ParseFailure;
+  block->setTerminator(termInst);
 
   return ParseSuccess;
 }
 
 
+/// Parse the terminator instruction for a basic block.
+///
+///   terminator-stmt ::= `br` bb-id branch-use-list?
+///   branch-use-list ::= `(` ssa-use-and-type-list? `)`
+///   terminator-stmt ::=
+///     `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
+///   terminator-stmt ::= `return` ssa-use-and-type-list?
+///
+TerminatorInst *Parser::parseTerminator(BasicBlock *currentBB,
+                                        CFGFunctionParserState &functionState) {
+  switch (curToken.getKind()) {
+  default:
+    return (emitError("expected terminator at end of basic block"), nullptr);
+
+  case Token::kw_return:
+    consumeToken(Token::kw_return);
+    return new ReturnInst(currentBB);
+
+  case Token::kw_br: {
+    consumeToken(Token::kw_br);
+    auto destBB = functionState.getBlockNamed(curToken.getSpelling(),
+                                              curToken.getLoc());
+    if (!consumeIf(Token::bare_identifier))
+      return (emitError("expected basic block name"), nullptr);
+    return new BranchInst(destBB, currentBB);
+  }
+  }
+}
+
+
 //===----------------------------------------------------------------------===//
 // Top-level entity parsing.
 //===----------------------------------------------------------------------===//