Improve management of instructions and basic blocks by having their inclusion
in a container automatically maintain their parent pointers, and change storage
from std::vector to the proper llvm::iplist type.

PiperOrigin-RevId: 202889037
diff --git a/lib/Parser/Parser.cpp b/lib/Parser/Parser.cpp
index 1bfa331..91f80e2 100644
--- a/lib/Parser/Parser.cpp
+++ b/lib/Parser/Parser.cpp
@@ -153,10 +153,8 @@
   ParseResult parseBasicBlock(CFGFunctionParserState &functionState);
   MLStatement *parseMLStatement(MLFunction *currentFunction);
 
-  ParseResult parseCFGOperation(BasicBlock *currentBB,
-                                CFGFunctionParserState &functionState);
-  ParseResult parseTerminator(BasicBlock *currentBB,
-                              CFGFunctionParserState &functionState);
+  OperationInst *parseCFGOperation(CFGFunctionParserState &functionState);
+  TerminatorInst *parseTerminator(CFGFunctionParserState &functionState);
 
 };
 } // end anonymous namespace
@@ -792,7 +790,7 @@
   BasicBlock *getBlockNamed(StringRef name, SMLoc loc) {
     auto &blockAndLoc = blocksByName[name];
     if (!blockAndLoc.first) {
-      blockAndLoc.first = new BasicBlock(function);
+      blockAndLoc.first = new BasicBlock();
       blockAndLoc.second = loc;
     }
     return blockAndLoc.first;
@@ -834,7 +832,7 @@
   // 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())
+    if (!bb->getFunction())
       return emitError(elt.second.second,
                        "reference to an undefined basic block '" +
                        elt.first() + "'");
@@ -861,20 +859,11 @@
 
   // If this block has already been parsed, then this is a redefinition with the
   // same block name.
-  if (block->getTerminator())
+  if (block->getFunction())
     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());
-  }
+  // Add the block to the function.
+  functionState.function->push_back(block);
 
   // TODO: parse bb argument list.
 
@@ -883,12 +872,17 @@
 
   // Parse the list of operations that make up the body of the block.
   while (curToken.isNot(Token::kw_return, Token::kw_br)) {
-    if (parseCFGOperation(block, functionState))
+    auto *inst = parseCFGOperation(functionState);
+    if (!inst)
       return ParseFailure;
+
+    block->getOperations().push_back(inst);
   }
 
-  if (parseTerminator(block, functionState))
+  auto *term = parseTerminator(functionState);
+  if (!term)
     return ParseFailure;
+  block->setTerminator(term);
 
   return ParseSuccess;
 }
@@ -903,33 +897,29 @@
 ///    (ssa-id `=`)? string '(' ssa-use-list? ')' attribute-dict?
 ///    `:` function-type
 ///
-ParseResult Parser::
-parseCFGOperation(BasicBlock *currentBB,
-                  CFGFunctionParserState &functionState) {
+OperationInst *Parser::
+parseCFGOperation(CFGFunctionParserState &functionState) {
 
   // TODO: parse ssa-id.
 
   if (curToken.isNot(Token::string))
-    return emitError("expected operation name in quotes");
+    return (emitError("expected operation name in quotes"), nullptr);
 
   auto name = curToken.getStringValue();
   if (name.empty())
-    return emitError("empty operation name is invalid");
+    return (emitError("empty operation name is invalid"), nullptr);
 
   consumeToken(Token::string);
 
   if (!consumeIf(Token::l_paren))
-    return emitError("expected '(' in operation");
+    return (emitError("expected '(' in operation"), nullptr);
 
   // TODO: Parse operands.
   if (!consumeIf(Token::r_paren))
-    return emitError("expected '(' in operation");
+    return (emitError("expected '(' in operation"), nullptr);
 
   auto nameId = Identifier::get(name, context);
-  new OperationInst(nameId, currentBB);
-
-  // TODO: add instruction the per-function symbol table.
-  return ParseSuccess;
+  return new OperationInst(nameId);
 }
 
 
@@ -941,25 +931,22 @@
 ///     `cond_br` ssa-use `,` bb-id branch-use-list? `,` bb-id branch-use-list?
 ///   terminator-stmt ::= `return` ssa-use-and-type-list?
 ///
-ParseResult Parser::parseTerminator(BasicBlock *currentBB,
-                                    CFGFunctionParserState &functionState) {
+TerminatorInst *Parser::parseTerminator(CFGFunctionParserState &functionState) {
   switch (curToken.getKind()) {
   default:
-    return emitError("expected terminator at end of basic block");
+    return (emitError("expected terminator at end of basic block"), nullptr);
 
   case Token::kw_return:
     consumeToken(Token::kw_return);
-    new ReturnInst(currentBB);
-    return ParseSuccess;
+    return new ReturnInst();
 
   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");
-    new BranchInst(destBB, currentBB);
-    return ParseSuccess;
+      return (emitError("expected basic block name"), nullptr);
+    return new BranchInst(destBB);
   }
   }
 }