1*927b7074SRiver Riddle //===- SymbolTable.cpp - MLIR Symbol Table Class --------------------------===//
2*927b7074SRiver Riddle //
3*927b7074SRiver Riddle // Copyright 2019 The MLIR Authors.
4*927b7074SRiver Riddle //
5*927b7074SRiver Riddle // Licensed under the Apache License, Version 2.0 (the "License");
6*927b7074SRiver Riddle // you may not use this file except in compliance with the License.
7*927b7074SRiver Riddle // You may obtain a copy of the License at
8*927b7074SRiver Riddle //
9*927b7074SRiver Riddle //   http://www.apache.org/licenses/LICENSE-2.0
10*927b7074SRiver Riddle //
11*927b7074SRiver Riddle // Unless required by applicable law or agreed to in writing, software
12*927b7074SRiver Riddle // distributed under the License is distributed on an "AS IS" BASIS,
13*927b7074SRiver Riddle // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*927b7074SRiver Riddle // See the License for the specific language governing permissions and
15*927b7074SRiver Riddle // limitations under the License.
16*927b7074SRiver Riddle // =============================================================================
17*927b7074SRiver Riddle 
18*927b7074SRiver Riddle #include "mlir/IR/SymbolTable.h"
19*927b7074SRiver Riddle #include "mlir/IR/Function.h"
20*927b7074SRiver Riddle 
21*927b7074SRiver Riddle using namespace mlir;
22*927b7074SRiver Riddle 
23*927b7074SRiver Riddle /// Look up a symbol with the specified name, returning null if no such name
24*927b7074SRiver Riddle /// exists. Names never include the @ on them.
25*927b7074SRiver Riddle Function *SymbolTable::lookup(StringRef name) const {
26*927b7074SRiver Riddle   return lookup(Identifier::get(name, context));
27*927b7074SRiver Riddle }
28*927b7074SRiver Riddle 
29*927b7074SRiver Riddle /// Look up a symbol with the specified name, returning null if no such name
30*927b7074SRiver Riddle /// exists. Names never include the @ on them.
31*927b7074SRiver Riddle Function *SymbolTable::lookup(Identifier name) const {
32*927b7074SRiver Riddle   return symbolTable.lookup(name);
33*927b7074SRiver Riddle }
34*927b7074SRiver Riddle 
35*927b7074SRiver Riddle /// Erase the given symbol from the table.
36*927b7074SRiver Riddle void SymbolTable::erase(Function *symbol) {
37*927b7074SRiver Riddle   auto it = symbolTable.find(symbol->getName());
38*927b7074SRiver Riddle   if (it != symbolTable.end() && it->second == symbol)
39*927b7074SRiver Riddle     symbolTable.erase(it);
40*927b7074SRiver Riddle }
41*927b7074SRiver Riddle 
42*927b7074SRiver Riddle /// Insert a new symbol into the table, and rename it as necessary to avoid
43*927b7074SRiver Riddle /// collisions.
44*927b7074SRiver Riddle void SymbolTable::insert(Function *symbol) {
45*927b7074SRiver Riddle   // Add this symbol to the symbol table, uniquing the name if a conflict is
46*927b7074SRiver Riddle   // detected.
47*927b7074SRiver Riddle   if (symbolTable.insert({symbol->getName(), symbol}).second)
48*927b7074SRiver Riddle     return;
49*927b7074SRiver Riddle 
50*927b7074SRiver Riddle   // If a conflict was detected, then the function will not have been added to
51*927b7074SRiver Riddle   // the symbol table.  Try suffixes until we get to a unique name that works.
52*927b7074SRiver Riddle   SmallString<128> nameBuffer(symbol->getName());
53*927b7074SRiver Riddle   unsigned originalLength = nameBuffer.size();
54*927b7074SRiver Riddle 
55*927b7074SRiver Riddle   // Iteratively try suffixes until we find one that isn't used.  We use a
56*927b7074SRiver Riddle   // module level uniquing counter to avoid N^2 behavior.
57*927b7074SRiver Riddle   do {
58*927b7074SRiver Riddle     nameBuffer.resize(originalLength);
59*927b7074SRiver Riddle     nameBuffer += '_';
60*927b7074SRiver Riddle     nameBuffer += std::to_string(uniquingCounter++);
61*927b7074SRiver Riddle     symbol->setName(Identifier::get(nameBuffer, context));
62*927b7074SRiver Riddle   } while (!symbolTable.insert({symbol->getName(), symbol}).second);
63*927b7074SRiver Riddle }
64