Add basic parser support for operands:
 - This introduces a new FunctionParser base class to handle logic common
   between the kinds of functions we have, e.g. ssa operand/def parsing.
 - This introduces a basic symbol table (without support for forward
   references!) and links defs and uses.
 - CFG functions now parse and build operand lists for operations.  The printer
   isn't set up for them yet tho.

PiperOrigin-RevId: 205246110
diff --git a/lib/Parser/Parser.cpp b/lib/Parser/Parser.cpp
index d220787..7fbbf9b 100644
--- a/lib/Parser/Parser.cpp
+++ b/lib/Parser/Parser.cpp
@@ -84,8 +84,8 @@
 
 namespace {
 
-typedef std::function<Operation *(Identifier, ArrayRef<Type *>,
-                                  ArrayRef<NamedAttribute>)>
+typedef std::function<Operation *(Identifier, ArrayRef<SSAValue *>,
+                                  ArrayRef<Type *>, ArrayRef<NamedAttribute>)>
     CreateOperationFunction;
 
 /// This class implement support for parsing global entities like types and
@@ -165,15 +165,6 @@
   AffineMap *parseAffineMapInline();
   AffineMap *parseAffineMapReference();
 
-  // SSA
-  ParseResult parseSSAUse();
-  ParseResult parseOptionalSSAUseList(Token::Kind endToken);
-  ParseResult parseSSAUseAndType();
-  ParseResult parseOptionalSSAUseAndTypeList(Token::Kind endToken);
-
-  // Operations
-  ParseResult parseOperation(const CreateOperationFunction &createOpFunc);
-
 private:
   // The Parser is subclassed and reinstantiated.  Do not add additional
   // non-trivial state here, add it to the ParserState class.
@@ -1171,25 +1162,96 @@
 }
 
 //===----------------------------------------------------------------------===//
-// SSA
+// FunctionParser
 //===----------------------------------------------------------------------===//
 
+namespace {
+/// This class contains parser state that is common across CFG and ML functions,
+/// notably for dealing with operations and SSA values.
+class FunctionParser : public Parser {
+public:
+  FunctionParser(ParserState &state) : Parser(state) {}
+
+  /// This represents a use of an SSA value in the program.  This tracks
+  /// location information in case this ends up being a use of an undefined
+  /// value.
+  typedef std::pair<StringRef, SMLoc> SSAUseInfo;
+
+  /// Given a reference to an SSA value and its type, return a reference.  This
+  /// returns null on failure.
+  SSAValue *resolveSSAUse(SSAUseInfo useInfo, Type *type);
+
+  /// Register a definition of a value with the symbol table.
+  ParseResult addDefinition(SSAUseInfo useInfo, SSAValue *value);
+
+  // SSA parsing productions.
+  ParseResult parseSSAUse(SSAUseInfo &result);
+  ParseResult parseOptionalSSAUseList(Token::Kind endToken,
+                                      SmallVectorImpl<SSAUseInfo> &results);
+  SSAValue *parseSSAUseAndType();
+  ParseResult
+  parseOptionalSSAUseAndTypeList(Token::Kind endToken,
+                                 SmallVectorImpl<SSAValue *> &results);
+
+  // Operations
+  ParseResult parseOperation(const CreateOperationFunction &createOpFunc);
+
+private:
+  /// This keeps track of all of the SSA values we are tracking, indexed by
+  /// their name (either an identifier or a number).
+  llvm::StringMap<std::pair<SSAValue *, SMLoc>> values;
+};
+} // end anonymous namespace
+
+/// Given an unbound reference to an SSA value and its type, return a the value
+/// it specifies.  This returns null on failure.
+SSAValue *FunctionParser::resolveSSAUse(SSAUseInfo useInfo, Type *type) {
+  // If we have already seen a value of this name, return it.
+  auto it = values.find(useInfo.first);
+  if (it != values.end()) {
+    // Check that the type matches the other uses.
+    auto result = it->second.first;
+    if (result->getType() == type)
+      return result;
+
+    emitError(useInfo.second, "use of value '" + useInfo.first.str() +
+                                  "' expects different type than prior uses");
+    emitError(it->second.second, "prior use here");
+    return nullptr;
+  }
+
+  // Otherwise we have a forward reference.
+  // TODO: Handle forward references.
+  emitError(useInfo.second, "undeclared or forward reference");
+  return nullptr;
+}
+
+/// Register a definition of a value with the symbol table.
+ParseResult FunctionParser::addDefinition(SSAUseInfo useInfo, SSAValue *value) {
+
+  // If this is the first definition of this thing, then we are trivially done.
+  auto insertInfo = values.insert({useInfo.first, {value, useInfo.second}});
+  if (insertInfo.second)
+    return ParseSuccess;
+
+  // If we already had a value, replace it with the new one and remove the
+  // placeholder, only if it was a forward ref.
+  // TODO: Handle forward references.
+  emitError(useInfo.second, "redefinition of SSA value " + useInfo.first.str());
+  return ParseFailure;
+}
+
 /// Parse a SSA operand for an instruction or statement.
 ///
 ///   ssa-use ::= ssa-id | ssa-constant
+/// TODO: SSA Constants.
 ///
-ParseResult Parser::parseSSAUse() {
-  if (getToken().is(Token::percent_identifier)) {
-    StringRef name = getTokenSpelling().drop_front();
-    consumeToken(Token::percent_identifier);
-    // TODO: Return this use.
-    (void)name;
-    return ParseSuccess;
-  }
-
-  // TODO: Parse SSA constants.
-
-  return emitError("expected SSA operand");
+ParseResult FunctionParser::parseSSAUse(SSAUseInfo &result) {
+  result.first = getTokenSpelling();
+  result.second = getToken().getLoc();
+  if (!consumeIf(Token::percent_identifier))
+    return emitError("expected SSA operand");
+  return ParseSuccess;
 }
 
 /// Parse a (possibly empty) list of SSA operands.
@@ -1197,42 +1259,51 @@
 ///   ssa-use-list ::= ssa-use (`,` ssa-use)*
 ///   ssa-use-list-opt ::= ssa-use-list?
 ///
-ParseResult Parser::parseOptionalSSAUseList(Token::Kind endToken) {
-  // TODO: Build and return this.
-  return parseCommaSeparatedList(
-      endToken, [&]() -> ParseResult { return parseSSAUse(); });
+ParseResult
+FunctionParser::parseOptionalSSAUseList(Token::Kind endToken,
+                                        SmallVectorImpl<SSAUseInfo> &results) {
+  return parseCommaSeparatedList(endToken, [&]() -> ParseResult {
+    SSAUseInfo result;
+    if (parseSSAUse(result))
+      return ParseFailure;
+    results.push_back(result);
+    return ParseSuccess;
+  });
 }
 
 /// Parse an SSA use with an associated type.
 ///
 ///   ssa-use-and-type ::= ssa-use `:` type
-ParseResult Parser::parseSSAUseAndType() {
-  if (parseSSAUse())
-    return ParseFailure;
+SSAValue *FunctionParser::parseSSAUseAndType() {
+  SSAUseInfo useInfo;
+  if (parseSSAUse(useInfo))
+    return nullptr;
 
   if (!consumeIf(Token::colon))
-    return emitError("expected ':' and type for SSA operand");
+    return (emitError("expected ':' and type for SSA operand"), nullptr);
 
-  if (!parseType())
-    return ParseFailure;
+  auto *type = parseType();
+  if (!type)
+    return nullptr;
 
-  return ParseSuccess;
+  return resolveSSAUse(useInfo, type);
 }
 
 /// Parse a (possibly empty) list of SSA operands with types.
 ///
 ///   ssa-use-and-type-list ::= ssa-use-and-type (`,` ssa-use-and-type)*
 ///
-ParseResult Parser::parseOptionalSSAUseAndTypeList(Token::Kind endToken) {
-  // TODO: Build and return this.
-  return parseCommaSeparatedList(
-      endToken, [&]() -> ParseResult { return parseSSAUseAndType(); });
+ParseResult FunctionParser::parseOptionalSSAUseAndTypeList(
+    Token::Kind endToken, SmallVectorImpl<SSAValue *> &results) {
+  return parseCommaSeparatedList(endToken, [&]() -> ParseResult {
+    if (auto *value = parseSSAUseAndType()) {
+      results.push_back(value);
+      return ParseSuccess;
+    }
+    return ParseFailure;
+  });
 }
 
-//===----------------------------------------------------------------------===//
-// Operations
-//===----------------------------------------------------------------------===//
-
 /// Parse the CFG or MLFunc operation.
 ///
 /// TODO(clattner): This is a change from the MLIR spec as written, it is an
@@ -1243,12 +1314,12 @@
 ///    `:` function-type
 ///
 ParseResult
-Parser::parseOperation(const CreateOperationFunction &createOpFunc) {
+FunctionParser::parseOperation(const CreateOperationFunction &createOpFunc) {
   auto loc = getToken().getLoc();
 
   StringRef resultID;
   if (getToken().is(Token::percent_identifier)) {
-    resultID = getTokenSpelling().drop_front();
+    resultID = getTokenSpelling();
     consumeToken(Token::percent_identifier);
     if (!consumeIf(Token::equal))
       return emitError("expected '=' after SSA name");
@@ -1267,7 +1338,8 @@
     return emitError("expected '(' to start operand list");
 
   // Parse the operand list.
-  parseOptionalSSAUseList(Token::r_paren);
+  SmallVector<SSAUseInfo, 8> operandInfos;
+  parseOptionalSSAUseList(Token::r_paren, operandInfos);
 
   SmallVector<NamedAttribute, 4> attributes;
   if (getToken().is(Token::l_brace)) {
@@ -1286,22 +1358,50 @@
   if (!fnType)
     return emitError(typeLoc, "expected function type");
 
-  // TODO: Don't drop result name and operand names on the floor.
+  // Check that we have the right number of types for the operands.
+  auto operandTypes = fnType->getInputs();
+  if (operandTypes.size() != operandInfos.size()) {
+    auto plural = "s"[operandInfos.size() == 1];
+    return emitError(typeLoc, "expected " + llvm::utostr(operandInfos.size()) +
+                                  " type" + plural +
+                                  " in operand list but had " +
+                                  llvm::utostr(operandTypes.size()));
+  }
+
+  // Resolve all of the operands.
+  SmallVector<SSAValue *, 8> operands;
+  for (unsigned i = 0, e = operandInfos.size(); i != e; ++i) {
+    operands.push_back(resolveSSAUse(operandInfos[i], operandTypes[i]));
+    if (!operands.back())
+      return ParseFailure;
+  }
+
   auto nameId = builder.getIdentifier(name);
-
-  auto oper = createOpFunc(nameId, fnType->getResults(), attributes);
-
-  if (!oper)
+  auto op = createOpFunc(nameId, operands, fnType->getResults(), attributes);
+  if (!op)
     return ParseFailure;
 
   // We just parsed an operation.  If it is a recognized one, verify that it
   // is structurally as we expect.  If not, produce an error with a reasonable
   // source location.
-  if (auto *opInfo = oper->getAbstractOperation(builder.getContext())) {
-    if (auto error = opInfo->verifyInvariants(oper))
+  if (auto *opInfo = op->getAbstractOperation(builder.getContext())) {
+    if (auto error = opInfo->verifyInvariants(op))
       return emitError(loc, error);
   }
 
+  // If the instruction had a name, register it.
+  if (!resultID.empty()) {
+    // FIXME: Add result infra to handle Stmt results as well to make this
+    // generic.
+    if (auto *inst = dyn_cast<OperationInst>(op)) {
+      if (inst->getResults().empty())
+        return emitError(loc, "cannot name an operation with no results");
+
+      // TODO: This should be getResult(0)
+      addDefinition({resultID, loc}, &inst->getResults()[0]);
+    }
+  }
+
   return ParseSuccess;
 }
 
@@ -1312,10 +1412,10 @@
 namespace {
 /// This is a specialized parser for CFGFunction's, maintaining the state
 /// transient to their bodies.
-class CFGFunctionParser : public Parser {
+class CFGFunctionParser : public FunctionParser {
 public:
   CFGFunctionParser(ParserState &state, CFGFunction *function)
-      : Parser(state), function(function), builder(function) {}
+      : FunctionParser(state), function(function), builder(function) {}
 
   ParseResult parseFunctionBody();
 
@@ -1397,7 +1497,8 @@
 
   // If an argument list is present, parse it.
   if (consumeIf(Token::l_paren)) {
-    if (parseOptionalSSAUseAndTypeList(Token::r_paren))
+    SmallVector<SSAValue *, 8> bbArgs;
+    if (parseOptionalSSAUseAndTypeList(Token::r_paren, bbArgs))
       return ParseFailure;
 
     // TODO: attach it.
@@ -1409,9 +1510,14 @@
   // Set the insertion point to the block we want to insert new operations into.
   builder.setInsertionPoint(block);
 
-  auto createOpFunc = [this](Identifier name, ArrayRef<Type *> resultTypes,
-                             ArrayRef<NamedAttribute> attrs) -> Operation * {
-    return builder.createOperation(name, {}, resultTypes, attrs);
+  auto createOpFunc = [&](Identifier name, ArrayRef<SSAValue *> operands,
+                          ArrayRef<Type *> resultTypes,
+                          ArrayRef<NamedAttribute> attrs) -> Operation * {
+    SmallVector<CFGValue *, 8> cfgOperands;
+    cfgOperands.reserve(operands.size());
+    for (auto *op : operands)
+      cfgOperands.push_back(cast<CFGValue>(op));
+    return builder.createOperation(name, cfgOperands, resultTypes, attrs);
   };
 
   // Parse the list of operations that make up the body of the block.
@@ -1460,10 +1566,10 @@
 
 namespace {
 /// Refined parser for MLFunction bodies.
-class MLFunctionParser : public Parser {
+class MLFunctionParser : public FunctionParser {
 public:
   MLFunctionParser(ParserState &state, MLFunction *function)
-      : Parser(state), function(function), builder(function) {}
+      : FunctionParser(state), function(function), builder(function) {}
 
   ParseResult parseFunctionBody();
 
@@ -1568,8 +1674,9 @@
 /// Parse a list of statements ending with `return` or `}`
 ///
 ParseResult MLFunctionParser::parseStatements(StmtBlock *block) {
-  auto createOpFunc = [this](Identifier name, ArrayRef<Type *> resultTypes,
-                             ArrayRef<NamedAttribute> attrs) -> Operation * {
+  auto createOpFunc = [&](Identifier name, ArrayRef<SSAValue *> operands,
+                          ArrayRef<Type *> resultTypes,
+                          ArrayRef<NamedAttribute> attrs) -> Operation * {
     return builder.createOperation(name, attrs);
   };