1927b7074SRiver Riddle //===- SymbolTable.cpp - MLIR Symbol Table Class --------------------------===//
2927b7074SRiver Riddle //
3927b7074SRiver Riddle // Copyright 2019 The MLIR Authors.
4927b7074SRiver Riddle //
5927b7074SRiver Riddle // Licensed under the Apache License, Version 2.0 (the "License");
6927b7074SRiver Riddle // you may not use this file except in compliance with the License.
7927b7074SRiver Riddle // You may obtain a copy of the License at
8927b7074SRiver Riddle //
9927b7074SRiver Riddle //   http://www.apache.org/licenses/LICENSE-2.0
10927b7074SRiver Riddle //
11927b7074SRiver Riddle // Unless required by applicable law or agreed to in writing, software
12927b7074SRiver Riddle // distributed under the License is distributed on an "AS IS" BASIS,
13927b7074SRiver Riddle // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14927b7074SRiver Riddle // See the License for the specific language governing permissions and
15927b7074SRiver Riddle // limitations under the License.
16927b7074SRiver Riddle // =============================================================================
17927b7074SRiver Riddle 
18927b7074SRiver Riddle #include "mlir/IR/SymbolTable.h"
198c47e2edSRiver Riddle #include "mlir/IR/Module.h"
20927b7074SRiver Riddle 
21927b7074SRiver Riddle using namespace mlir;
22927b7074SRiver Riddle 
238c47e2edSRiver Riddle /// Build a symbol table with the symbols within the given module.
24*e7d594bbSRiver Riddle SymbolTable::SymbolTable(ModuleOp module) : context(module.getContext()) {
25206e55ccSRiver Riddle   for (auto func : module) {
2654cd6a7eSRiver Riddle     auto inserted = symbolTable.insert({func.getName(), func});
278c47e2edSRiver Riddle     (void)inserted;
288c47e2edSRiver Riddle     assert(inserted.second &&
298c47e2edSRiver Riddle            "expected module to contain uniquely named functions");
308c47e2edSRiver Riddle   }
318c47e2edSRiver Riddle }
328c47e2edSRiver Riddle 
33927b7074SRiver Riddle /// Look up a symbol with the specified name, returning null if no such name
34927b7074SRiver Riddle /// exists. Names never include the @ on them.
3554cd6a7eSRiver Riddle Function SymbolTable::lookup(StringRef name) const {
36*e7d594bbSRiver Riddle   return symbolTable.lookup(name);
37927b7074SRiver Riddle }
38927b7074SRiver Riddle 
39927b7074SRiver Riddle /// Look up a symbol with the specified name, returning null if no such name
40927b7074SRiver Riddle /// exists. Names never include the @ on them.
4154cd6a7eSRiver Riddle Function SymbolTable::lookup(Identifier name) const {
42*e7d594bbSRiver Riddle   return lookup(name.strref());
43927b7074SRiver Riddle }
44927b7074SRiver Riddle 
45927b7074SRiver Riddle /// Erase the given symbol from the table.
4654cd6a7eSRiver Riddle void SymbolTable::erase(Function symbol) {
4754cd6a7eSRiver Riddle   auto it = symbolTable.find(symbol.getName());
48927b7074SRiver Riddle   if (it != symbolTable.end() && it->second == symbol)
49927b7074SRiver Riddle     symbolTable.erase(it);
50927b7074SRiver Riddle }
51927b7074SRiver Riddle 
52927b7074SRiver Riddle /// Insert a new symbol into the table, and rename it as necessary to avoid
53927b7074SRiver Riddle /// collisions.
5454cd6a7eSRiver Riddle void SymbolTable::insert(Function symbol) {
55927b7074SRiver Riddle   // Add this symbol to the symbol table, uniquing the name if a conflict is
56927b7074SRiver Riddle   // detected.
5754cd6a7eSRiver Riddle   if (symbolTable.insert({symbol.getName(), symbol}).second)
58927b7074SRiver Riddle     return;
59927b7074SRiver Riddle 
60927b7074SRiver Riddle   // If a conflict was detected, then the function will not have been added to
61927b7074SRiver Riddle   // the symbol table.  Try suffixes until we get to a unique name that works.
6254cd6a7eSRiver Riddle   SmallString<128> nameBuffer(symbol.getName());
63927b7074SRiver Riddle   unsigned originalLength = nameBuffer.size();
64927b7074SRiver Riddle 
65927b7074SRiver Riddle   // Iteratively try suffixes until we find one that isn't used.  We use a
66927b7074SRiver Riddle   // module level uniquing counter to avoid N^2 behavior.
67927b7074SRiver Riddle   do {
68927b7074SRiver Riddle     nameBuffer.resize(originalLength);
69927b7074SRiver Riddle     nameBuffer += '_';
70927b7074SRiver Riddle     nameBuffer += std::to_string(uniquingCounter++);
71*e7d594bbSRiver Riddle   } while (!symbolTable.insert({nameBuffer, symbol}).second);
72*e7d594bbSRiver Riddle   symbol.setName(nameBuffer);
73927b7074SRiver Riddle }
74