Implement a module-level symbol table for functions, enforcing uniqueness of
names across the module and auto-renaming conflicts.  Have the parser reject
malformed modules that have redefinitions.

PiperOrigin-RevId: 209227560
diff --git a/include/mlir/IR/Module.h b/include/mlir/IR/Module.h
index 8e45f8d..f6c543b 100644
--- a/include/mlir/IR/Module.h
+++ b/include/mlir/IR/Module.h
@@ -23,6 +23,7 @@
 #define MLIR_IR_MODULE_H
 
 #include "mlir/IR/Function.h"
+#include "llvm/ADT/DenseMap.h"
 #include "llvm/ADT/ilist.h"
 #include <vector>
 
@@ -36,8 +37,6 @@
 
   MLIRContext *getContext() const { return context; }
 
-  // TODO: We should have a symbol table for function names.
-
   /// This is the list of functions in the module.
   typedef llvm::iplist<Function> FunctionListType;
   FunctionListType &getFunctions() { return functions; }
@@ -58,6 +57,23 @@
   const_reverse_iterator rbegin() const { return functions.rbegin(); }
   const_reverse_iterator rend() const { return functions.rend(); }
 
+  // Interfaces for working with the symbol table.
+
+  /// Look up a function with the specified name, returning null if no such
+  /// name exists.
+  Function *getNamedFunction(StringRef name);
+  const Function *getNamedFunction(StringRef name) const {
+    return const_cast<Module *>(this)->getNamedFunction(name);
+  }
+
+  /// Look up a function with the specified name, returning null if no such
+  /// name exists.
+  Function *getNamedFunction(Identifier name);
+
+  const Function *getNamedFunction(Identifier name) const {
+    return const_cast<Module *>(this)->getNamedFunction(name);
+  }
+
   /// Perform (potentially expensive) checks of invariants, used to detect
   /// compiler bugs.  On error, this fills in the string and return true,
   /// or aborts if the string was not provided.
@@ -66,13 +82,23 @@
   void print(raw_ostream &os) const;
   void dump() const;
 
+private:
+  friend struct llvm::ilist_traits<Function>;
+
   /// getSublistAccess() - Returns pointer to member of function list
   static FunctionListType Module::*getSublistAccess(Function *) {
     return &Module::functions;
   }
 
-private:
   MLIRContext *context;
+
+  /// This is a mapping from a name to the function with that name.
+  llvm::DenseMap<Identifier, Function *> symbolTable;
+
+  /// This is used when name conflicts are detected.
+  unsigned uniquingCounter = 0;
+
+  /// This is the actual list of functions the module contains.
   FunctionListType functions;
 };
 } // end namespace mlir