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"
19*8c47e2edSRiver Riddle #include "mlir/IR/Module.h"
20927b7074SRiver Riddle 
21927b7074SRiver Riddle using namespace mlir;
22927b7074SRiver Riddle 
23*8c47e2edSRiver Riddle /// Build a symbol table with the symbols within the given module.
24*8c47e2edSRiver Riddle SymbolTable::SymbolTable(Module *module) : context(module->getContext()) {
25*8c47e2edSRiver Riddle   for (auto &func : *module) {
26*8c47e2edSRiver Riddle     auto inserted = symbolTable.insert({func.getName(), &func});
27*8c47e2edSRiver Riddle     (void)inserted;
28*8c47e2edSRiver Riddle     assert(inserted.second &&
29*8c47e2edSRiver Riddle            "expected module to contain uniquely named functions");
30*8c47e2edSRiver Riddle   }
31*8c47e2edSRiver Riddle }
32*8c47e2edSRiver 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.
35927b7074SRiver Riddle Function *SymbolTable::lookup(StringRef name) const {
36927b7074SRiver Riddle   return lookup(Identifier::get(name, context));
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.
41927b7074SRiver Riddle Function *SymbolTable::lookup(Identifier name) const {
42927b7074SRiver Riddle   return symbolTable.lookup(name);
43927b7074SRiver Riddle }
44927b7074SRiver Riddle 
45927b7074SRiver Riddle /// Erase the given symbol from the table.
46927b7074SRiver Riddle void SymbolTable::erase(Function *symbol) {
47927b7074SRiver 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.
54927b7074SRiver 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.
57927b7074SRiver 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.
62927b7074SRiver 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++);
71927b7074SRiver Riddle     symbol->setName(Identifier::get(nameBuffer, context));
72927b7074SRiver Riddle   } while (!symbolTable.insert({symbol->getName(), symbol}).second);
73927b7074SRiver Riddle }
74