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  }