Teach the asmprinter to print out operands for OperationInst's.  This
is still limited in several ways, which i'll build out in subsequent patches.

Rename the accessor for inst operands/results to make the Operand/Result
versions of these more obscure, allowing getOperand/getResult to traffic
in values (which is what - by far - most clients actually care about).

PiperOrigin-RevId: 205408439
diff --git a/lib/IR/AsmPrinter.cpp b/lib/IR/AsmPrinter.cpp
index 03d9b1d..31fd05c 100644
--- a/lib/IR/AsmPrinter.cpp
+++ b/lib/IR/AsmPrinter.cpp
@@ -38,6 +38,12 @@
 
 void Identifier::dump() const { print(llvm::errs()); }
 
+template <typename Container, typename UnaryFunctor>
+inline void interleaveComma(raw_ostream &os, const Container &c,
+                            UnaryFunctor each_fn) {
+  interleave(c.begin(), c.end(), each_fn, [&]() { os << ", "; });
+}
+
 //===----------------------------------------------------------------------===//
 // Module printing
 //===----------------------------------------------------------------------===//
@@ -222,9 +228,7 @@
   case Attribute::Kind::Array: {
     auto elts = cast<ArrayAttr>(attr)->getValue();
     os << '[';
-    interleave(elts,
-                [&](Attribute *attr) { print(attr); },
-                [&]() { os << ", "; });
+    interleaveComma(os, elts, [&](Attribute *attr) { print(attr); });
     os << ']';
     break;
   }
@@ -260,16 +264,14 @@
   case Type::Kind::Function: {
     auto *func = cast<FunctionType>(type);
     os << '(';
-    interleave(func->getInputs(), [&](Type *type) { os << *type; },
-               [&]() { os << ", "; });
+    interleaveComma(os, func->getInputs(), [&](Type *type) { os << *type; });
     os << ") -> ";
     auto results = func->getResults();
     if (results.size() == 1)
       os << *results[0];
     else {
       os << '(';
-      interleave(results, [&](Type *type) { os << *type; },
-                 [&]() { os << ", "; });
+      interleaveComma(os, results, [&](Type *type) { os << *type; });
       os << ')';
     }
     return;
@@ -331,9 +333,8 @@
   auto type = fn->getType();
 
   os << "@" << fn->getName() << '(';
-  interleave(type->getInputs(),
-             [&](Type *eltType) { moduleState->print(eltType); },
-             [&]() { os << ", "; });
+  interleaveComma(os, type->getInputs(),
+                  [&](Type *eltType) { moduleState->print(eltType); });
   os << ')';
 
   switch (type->getResults().size()) {
@@ -345,9 +346,8 @@
     break;
   default:
     os << " -> (";
-    interleave(type->getResults(),
-               [&](Type *eltType) { moduleState->print(eltType); },
-               [&]() { os << ", "; });
+    interleaveComma(os, type->getResults(),
+                    [&](Type *eltType) { moduleState->print(eltType); });
     os << ')';
     break;
   }
@@ -374,6 +374,26 @@
   raw_ostream &os;
   const ModuleState *moduleState;
   const OperationSet &operationSet;
+
+  void numberValueID(const SSAValue *value) {
+    assert(!valueIDs.count(value) && "Value numbered multiple times");
+    valueIDs[value] = nextValueID++;
+  }
+
+  void printValueID(const SSAValue *value) const {
+    // TODO: If this is the result of an operation with multiple results, look
+    // up the first result, and print the #32 syntax.
+    auto it = valueIDs.find(value);
+    if (it != valueIDs.end())
+      os << '%' << it->getSecond();
+    else
+      os << "<<INVALID SSA VALUE>>";
+  }
+
+private:
+  /// This is the value ID for each SSA value in the current function.
+  DenseMap<const SSAValue *, unsigned> valueIDs;
+  unsigned nextValueID = 0;
 };
 }  // end anonymous namespace
 
@@ -384,32 +404,72 @@
       operationSet(OperationSet::get(context)) {}
 
 void FunctionState::printOperation(const Operation *op) {
+  os << "  ";
+
+  // TODO: When we have SSAValue version of operands & results wired into
+  // Operation this check can go away.
+  if (auto *inst = dyn_cast<OperationInst>(op)) {
+    if (inst->getNumResults()) {
+      printValueID(inst->getResult(0));
+      os << " = ";
+    }
+  }
+
   // Check to see if this is a known operation.  If so, use the registered
   // custom printer hook.
   if (auto opInfo = operationSet.lookup(op->getName().str())) {
-    os << "  ";
     opInfo->printAssembly(op, os);
     return;
   }
 
+  // Otherwise use the standard verbose printing approach.
+
   // TODO: escape name if necessary.
-  os << "  \"" << op->getName().str() << "\"()";
+  os << "\"" << op->getName().str() << "\"(";
 
-  // FIXME: Print operand references.
+  // TODO: When we have SSAValue version of operands & results wired into
+  // Operation this check can go away.
+  if (auto *inst = dyn_cast<OperationInst>(op)) {
+    // TODO: Use getOperands() when we have it.
+    interleaveComma(
+        os, inst->getInstOperands(),
+        [&](const InstOperand &operand) { printValueID(operand.get()); });
+  }
 
+  os << ')';
   auto attrs = op->getAttrs();
   if (!attrs.empty()) {
     os << '{';
-    interleave(
-        attrs,
-        [&](NamedAttribute attr) {
-          os << attr.first << ": ";
-          moduleState->print(attr.second); },
-        [&]() { os << ", "; });
+    interleaveComma(os, attrs, [&](NamedAttribute attr) {
+      os << attr.first << ": ";
+      moduleState->print(attr.second);
+    });
     os << '}';
   }
 
-  // TODO: Print signature type once that is plumbed through to Operation.
+  // TODO: When we have SSAValue version of operands & results wired into
+  // Operation this check can go away.
+  if (auto *inst = dyn_cast<OperationInst>(op)) {
+    // Print the type signature of the operation.
+    os << " : (";
+    // TODO: Switch to getOperands() when we have it.
+    interleaveComma(os, inst->getInstOperands(), [&](const InstOperand &op) {
+      moduleState->print(op.get()->getType());
+    });
+    os << ") -> ";
+
+    // TODO: Switch to getResults() when we have it.
+    if (inst->getNumResults() == 1) {
+      moduleState->print(inst->getInstResult(0).getType());
+    } else {
+      os << '(';
+      interleaveComma(os, inst->getInstResults(),
+                      [&](const InstResult &result) {
+                        moduleState->print(result.getType());
+                      });
+      os << ')';
+    }
+  }
 }
 
 //===----------------------------------------------------------------------===//
@@ -441,6 +501,8 @@
 private:
   const CFGFunction *function;
   DenseMap<const BasicBlock *, unsigned> basicBlockIDs;
+
+  void numberBlock(const BasicBlock *block);
 };
 }  // end anonymous namespace
 
@@ -451,7 +513,23 @@
       function(function) {
   // Each basic block gets a unique ID per function.
   unsigned blockID = 0;
-  for (auto &block : *function) basicBlockIDs[&block] = blockID++;
+  for (auto &block : *function) {
+    basicBlockIDs[&block] = blockID++;
+    numberBlock(&block);
+  }
+}
+
+/// Number all of the SSA values in the specified basic block.
+void CFGFunctionState::numberBlock(const BasicBlock *block) {
+  // TODO: basic block arguments.
+  for (auto &op : *block) {
+    // We number instruction that have results, and we only number the first
+    // result.
+    if (op.getNumResults() != 0)
+      numberValueID(op.getResult(0));
+  }
+
+  // Terminators do not define values.
 }
 
 void CFGFunctionState::print() {
@@ -489,29 +567,6 @@
 
 void CFGFunctionState::print(const OperationInst *inst) {
   printOperation(inst);
-
-  // FIXME: Move this into printOperation when Operation has operands and
-  // results
-
-  // Print the type signature of the operation.
-  os << " : (";
-  interleave(
-      inst->getOperands(),
-      [&](const InstOperand &op) { moduleState->print(op.get()->getType()); },
-      [&]() { os << ", "; });
-  os << ") -> ";
-
-  auto resultList = inst->getResults();
-  if (resultList.size() == 1) {
-    moduleState->print(resultList[0].getType());
-  } else {
-    os << '(';
-    interleave(
-        resultList,
-        [&](const InstResult &result) { moduleState->print(result.getType()); },
-        [&]() { os << ", "; });
-    os << ')';
-  }
 }
 void CFGFunctionState::print(const BranchInst *inst) {
   os << "  br bb" << getBBID(inst->getDest());
@@ -753,8 +808,7 @@
   assert(!getResults().empty());
   // Result affine expressions.
   os << " -> (";
-  interleave(getResults(), [&](AffineExpr *expr) { os << *expr; },
-             [&]() { os << ", "; });
+  interleaveComma(os, getResults(), [&](AffineExpr *expr) { os << *expr; });
   os << ")";
 
   if (!isBounded()) {
@@ -763,8 +817,7 @@
 
   // Print range sizes for bounded affine maps.
   os << " size (";
-  interleave(getRangeSizes(), [&](AffineExpr *expr) { os << *expr; },
-             [&]() { os << ", "; });
+  interleaveComma(os, getRangeSizes(), [&](AffineExpr *expr) { os << *expr; });
   os << ")";
 }