github.com/johnnyeven/libtools@v0.0.0-20191126065708-61829c1adf46/third_party/mlir/lib/IR/SymbolTable.cpp (about) 1 //===- SymbolTable.cpp - MLIR Symbol Table Class --------------------------===// 2 // 3 // Copyright 2019 The MLIR Authors. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 // ============================================================================= 17 18 #include "mlir/IR/SymbolTable.h" 19 #include "llvm/ADT/SmallString.h" 20 21 using namespace mlir; 22 23 /// Build a symbol table with the symbols within the given operation. 24 SymbolTable::SymbolTable(Operation *op) : context(op->getContext()) { 25 assert(op->hasTrait<OpTrait::SymbolTable>() && 26 "expected operation to have SymbolTable trait"); 27 assert(op->getNumRegions() == 1 && 28 "expected operation to have a single region"); 29 30 for (auto &block : op->getRegion(0)) { 31 for (auto &op : block) { 32 auto nameAttr = op.getAttrOfType<StringAttr>(getSymbolAttrName()); 33 if (!nameAttr) 34 continue; 35 36 auto inserted = symbolTable.insert({nameAttr.getValue(), &op}); 37 (void)inserted; 38 assert(inserted.second && 39 "expected region to contain uniquely named symbol operations"); 40 } 41 } 42 } 43 44 /// Look up a symbol with the specified name, returning null if no such name 45 /// exists. Names never include the @ on them. 46 Operation *SymbolTable::lookup(StringRef name) const { 47 return symbolTable.lookup(name); 48 } 49 50 /// Erase the given symbol from the table. 51 void SymbolTable::erase(Operation *symbol) { 52 auto nameAttr = symbol->getAttrOfType<StringAttr>(getSymbolAttrName()); 53 assert(nameAttr && "expected valid 'name' attribute"); 54 55 auto it = symbolTable.find(nameAttr.getValue()); 56 if (it != symbolTable.end() && it->second == symbol) 57 symbolTable.erase(it); 58 } 59 60 /// Insert a new symbol into the table, and rename it as necessary to avoid 61 /// collisions. 62 void SymbolTable::insert(Operation *symbol) { 63 auto nameAttr = symbol->getAttrOfType<StringAttr>(getSymbolAttrName()); 64 assert(nameAttr && "expected valid 'name' attribute"); 65 66 // Add this symbol to the symbol table, uniquing the name if a conflict is 67 // detected. 68 if (symbolTable.insert({nameAttr.getValue(), symbol}).second) 69 return; 70 71 // If a conflict was detected, then the symbol will not have been added to 72 // the symbol table. Try suffixes until we get to a unique name that works. 73 SmallString<128> nameBuffer(nameAttr.getValue()); 74 unsigned originalLength = nameBuffer.size(); 75 76 // Iteratively try suffixes until we find one that isn't used. 77 do { 78 nameBuffer.resize(originalLength); 79 nameBuffer += '_'; 80 nameBuffer += std::to_string(uniquingCounter++); 81 } while (!symbolTable.insert({nameBuffer, symbol}).second); 82 symbol->setAttr(getSymbolAttrName(), StringAttr::get(nameBuffer, context)); 83 } 84 85 //===----------------------------------------------------------------------===// 86 // SymbolTable Trait Types 87 //===----------------------------------------------------------------------===// 88 89 LogicalResult OpTrait::impl::verifySymbolTable(Operation *op) { 90 if (op->getNumRegions() != 1) 91 return op->emitOpError() 92 << "Operations with a 'SymbolTable' must have exactly one region"; 93 94 // Check that all symboles are uniquely named within child regions. 95 llvm::StringMap<Location> nameToOrigLoc; 96 for (auto &block : op->getRegion(0)) { 97 for (auto &op : block) { 98 // Check for a symbol name attribute. 99 auto nameAttr = 100 op.getAttrOfType<StringAttr>(mlir::SymbolTable::getSymbolAttrName()); 101 if (!nameAttr) 102 continue; 103 104 // Try to insert this symbol into the table. 105 auto it = nameToOrigLoc.try_emplace(nameAttr.getValue(), op.getLoc()); 106 if (!it.second) 107 return op.emitError() 108 .append("redefinition of symbol named '", nameAttr.getValue(), "'") 109 .attachNote(it.first->second) 110 .append("see existing symbol definition here"); 111 } 112 } 113 return success(); 114 }