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*ee8e8b55SRiver Riddle #include "llvm/ADT/SmallString.h" 20927b7074SRiver Riddle 21927b7074SRiver Riddle using namespace mlir; 22927b7074SRiver Riddle 23*ee8e8b55SRiver Riddle /// Build a symbol table with the symbols within the given operation. 24*ee8e8b55SRiver Riddle SymbolTable::SymbolTable(Operation *op) : context(op->getContext()) { 25*ee8e8b55SRiver Riddle assert(op->hasTrait<OpTrait::SymbolTable>() && 26*ee8e8b55SRiver Riddle "expected operation to have SymbolTable trait"); 27*ee8e8b55SRiver Riddle assert(op->getNumRegions() == 1 && 28*ee8e8b55SRiver Riddle "expected operation to have a single region"); 29*ee8e8b55SRiver Riddle 30*ee8e8b55SRiver Riddle for (auto &block : op->getRegion(0)) { 31*ee8e8b55SRiver Riddle for (auto &op : block) { 32*ee8e8b55SRiver Riddle auto nameAttr = op.getAttrOfType<StringAttr>(getSymbolAttrName()); 33*ee8e8b55SRiver Riddle if (!nameAttr) 34*ee8e8b55SRiver Riddle continue; 35*ee8e8b55SRiver Riddle 36*ee8e8b55SRiver Riddle auto inserted = symbolTable.insert({nameAttr.getValue(), &op}); 378c47e2edSRiver Riddle (void)inserted; 388c47e2edSRiver Riddle assert(inserted.second && 39*ee8e8b55SRiver Riddle "expected region to contain uniquely named symbol operations"); 40*ee8e8b55SRiver Riddle } 418c47e2edSRiver Riddle } 428c47e2edSRiver Riddle } 438c47e2edSRiver Riddle 44927b7074SRiver Riddle /// Look up a symbol with the specified name, returning null if no such name 45927b7074SRiver Riddle /// exists. Names never include the @ on them. 46*ee8e8b55SRiver Riddle Operation *SymbolTable::lookup(StringRef name) const { 47e7d594bbSRiver Riddle return symbolTable.lookup(name); 48927b7074SRiver Riddle } 49927b7074SRiver Riddle 50927b7074SRiver Riddle /// Erase the given symbol from the table. 51*ee8e8b55SRiver Riddle void SymbolTable::erase(Operation *symbol) { 52*ee8e8b55SRiver Riddle auto nameAttr = symbol->getAttrOfType<StringAttr>(getSymbolAttrName()); 53*ee8e8b55SRiver Riddle assert(nameAttr && "expected valid 'name' attribute"); 54*ee8e8b55SRiver Riddle 55*ee8e8b55SRiver Riddle auto it = symbolTable.find(nameAttr.getValue()); 56927b7074SRiver Riddle if (it != symbolTable.end() && it->second == symbol) 57927b7074SRiver Riddle symbolTable.erase(it); 58927b7074SRiver Riddle } 59927b7074SRiver Riddle 60927b7074SRiver Riddle /// Insert a new symbol into the table, and rename it as necessary to avoid 61927b7074SRiver Riddle /// collisions. 62*ee8e8b55SRiver Riddle void SymbolTable::insert(Operation *symbol) { 63*ee8e8b55SRiver Riddle auto nameAttr = symbol->getAttrOfType<StringAttr>(getSymbolAttrName()); 64*ee8e8b55SRiver Riddle assert(nameAttr && "expected valid 'name' attribute"); 65*ee8e8b55SRiver Riddle 66927b7074SRiver Riddle // Add this symbol to the symbol table, uniquing the name if a conflict is 67927b7074SRiver Riddle // detected. 68*ee8e8b55SRiver Riddle if (symbolTable.insert({nameAttr.getValue(), symbol}).second) 69927b7074SRiver Riddle return; 70927b7074SRiver Riddle 71*ee8e8b55SRiver Riddle // If a conflict was detected, then the symbol will not have been added to 72927b7074SRiver Riddle // the symbol table. Try suffixes until we get to a unique name that works. 73*ee8e8b55SRiver Riddle SmallString<128> nameBuffer(nameAttr.getValue()); 74927b7074SRiver Riddle unsigned originalLength = nameBuffer.size(); 75927b7074SRiver Riddle 76*ee8e8b55SRiver Riddle // Iteratively try suffixes until we find one that isn't used. 77927b7074SRiver Riddle do { 78927b7074SRiver Riddle nameBuffer.resize(originalLength); 79927b7074SRiver Riddle nameBuffer += '_'; 80927b7074SRiver Riddle nameBuffer += std::to_string(uniquingCounter++); 81e7d594bbSRiver Riddle } while (!symbolTable.insert({nameBuffer, symbol}).second); 82*ee8e8b55SRiver Riddle symbol->setAttr(getSymbolAttrName(), StringAttr::get(nameBuffer, context)); 83*ee8e8b55SRiver Riddle } 84*ee8e8b55SRiver Riddle 85*ee8e8b55SRiver Riddle //===----------------------------------------------------------------------===// 86*ee8e8b55SRiver Riddle // SymbolTable Trait Types 87*ee8e8b55SRiver Riddle //===----------------------------------------------------------------------===// 88*ee8e8b55SRiver Riddle 89*ee8e8b55SRiver Riddle LogicalResult OpTrait::impl::verifySymbolTable(Operation *op) { 90*ee8e8b55SRiver Riddle if (op->getNumRegions() != 1) 91*ee8e8b55SRiver Riddle return op->emitOpError() 92*ee8e8b55SRiver Riddle << "Operations with a 'SymbolTable' must have exactly one region"; 93*ee8e8b55SRiver Riddle 94*ee8e8b55SRiver Riddle // Check that all symboles are uniquely named within child regions. 95*ee8e8b55SRiver Riddle llvm::StringMap<Location> nameToOrigLoc; 96*ee8e8b55SRiver Riddle for (auto &block : op->getRegion(0)) { 97*ee8e8b55SRiver Riddle for (auto &op : block) { 98*ee8e8b55SRiver Riddle // Check for a symbol name attribute. 99*ee8e8b55SRiver Riddle auto nameAttr = 100*ee8e8b55SRiver Riddle op.getAttrOfType<StringAttr>(mlir::SymbolTable::getSymbolAttrName()); 101*ee8e8b55SRiver Riddle if (!nameAttr) 102*ee8e8b55SRiver Riddle continue; 103*ee8e8b55SRiver Riddle 104*ee8e8b55SRiver Riddle // Try to insert this symbol into the table. 105*ee8e8b55SRiver Riddle auto it = nameToOrigLoc.try_emplace(nameAttr.getValue(), op.getLoc()); 106*ee8e8b55SRiver Riddle if (!it.second) 107*ee8e8b55SRiver Riddle return op.emitError() 108*ee8e8b55SRiver Riddle .append("redefinition of symbol named '", nameAttr.getValue(), "'") 109*ee8e8b55SRiver Riddle .attachNote(it.first->second) 110*ee8e8b55SRiver Riddle .append("see existing symbol definition here"); 111*ee8e8b55SRiver Riddle } 112*ee8e8b55SRiver Riddle } 113*ee8e8b55SRiver Riddle return success(); 114927b7074SRiver Riddle } 115