brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.3 KiB · 45cef9c Raw
213 lines · cpp
1//===- TransformDialect.cpp - Transform Dialect Definition ----------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "mlir/Dialect/Transform/IR/TransformDialect.h"10#include "mlir/Analysis/CallGraph.h"11#include "mlir/Dialect/Transform/IR/TransformOps.h"12#include "mlir/Dialect/Transform/IR/TransformTypes.h"13#include "mlir/Dialect/Transform/IR/Utils.h"14#include "mlir/Dialect/Transform/Interfaces/TransformInterfaces.h"15#include "mlir/IR/DialectImplementation.h"16#include "mlir/IR/Verifier.h"17#include "llvm/ADT/SCCIterator.h"18#include "llvm/ADT/TypeSwitch.h"19 20using namespace mlir;21 22#include "mlir/Dialect/Transform/IR/TransformDialect.cpp.inc"23 24#define GET_ATTRDEF_CLASSES25#include "mlir/Dialect/Transform/IR/TransformAttrs.cpp.inc"26 27#ifndef NDEBUG28void transform::detail::checkImplementsTransformOpInterface(29    StringRef name, MLIRContext *context) {30  // Since the operation is being inserted into the Transform dialect and the31  // dialect does not implement the interface fallback, only check for the op32  // itself having the interface implementation.33  RegisteredOperationName opName =34      *RegisteredOperationName::lookup(name, context);35  assert((opName.hasInterface<TransformOpInterface>() ||36          opName.hasInterface<PatternDescriptorOpInterface>() ||37          opName.hasInterface<ConversionPatternDescriptorOpInterface>() ||38          opName.hasInterface<TypeConverterBuilderOpInterface>() ||39          opName.hasTrait<OpTrait::IsTerminator>()) &&40         "non-terminator ops injected into the transform dialect must "41         "implement TransformOpInterface or PatternDescriptorOpInterface or "42         "ConversionPatternDescriptorOpInterface");43  if (!opName.hasInterface<PatternDescriptorOpInterface>() &&44      !opName.hasInterface<ConversionPatternDescriptorOpInterface>() &&45      !opName.hasInterface<TypeConverterBuilderOpInterface>()) {46    assert(opName.hasInterface<MemoryEffectOpInterface>() &&47           "ops injected into the transform dialect must implement "48           "MemoryEffectsOpInterface");49  }50}51 52void transform::detail::checkImplementsTransformHandleTypeInterface(53    TypeID typeID, MLIRContext *context) {54  const auto &abstractType = AbstractType::lookup(typeID, context);55  assert((abstractType.hasInterface(56              TransformHandleTypeInterface::getInterfaceID()) ||57          abstractType.hasInterface(58              TransformParamTypeInterface::getInterfaceID()) ||59          abstractType.hasInterface(60              TransformValueHandleTypeInterface::getInterfaceID())) &&61         "expected Transform dialect type to implement one of the three "62         "interfaces");63}64#endif // NDEBUG65 66void transform::TransformDialect::initialize() {67  // Using the checked versions to enable the same assertions as for the ops68  // from extensions.69  addOperationsChecked<70#define GET_OP_LIST71#include "mlir/Dialect/Transform/IR/TransformOps.cpp.inc"72      >();73  initializeTypes();74  addAttributes<75#define GET_ATTRDEF_LIST76#include "mlir/Dialect/Transform/IR/TransformAttrs.cpp.inc"77      >();78  initializeLibraryModule();79}80 81Type transform::TransformDialect::parseType(DialectAsmParser &parser) const {82  StringRef keyword;83  SMLoc loc = parser.getCurrentLocation();84  if (failed(parser.parseKeyword(&keyword)))85    return nullptr;86 87  auto it = typeParsingHooks.find(keyword);88  if (it == typeParsingHooks.end()) {89    parser.emitError(loc) << "unknown type mnemonic: " << keyword;90    return nullptr;91  }92 93  return it->getValue()(parser);94}95 96void transform::TransformDialect::printType(Type type,97                                            DialectAsmPrinter &printer) const {98  auto it = typePrintingHooks.find(type.getTypeID());99  assert(it != typePrintingHooks.end() && "printing unknown type");100  it->getSecond()(type, printer);101}102 103LogicalResult transform::TransformDialect::loadIntoLibraryModule(104    ::mlir::OwningOpRef<::mlir::ModuleOp> &&library) {105  return detail::mergeSymbolsInto(getLibraryModule(), std::move(library));106}107 108void transform::TransformDialect::initializeLibraryModule() {109  MLIRContext *context = getContext();110  auto loc =111      FileLineColLoc::get(context, "<transform-dialect-library-module>", 0, 0);112  libraryModule = ModuleOp::create(loc, "__transform_library");113  libraryModule.get()->setAttr(TransformDialect::kWithNamedSequenceAttrName,114                               UnitAttr::get(context));115}116 117void transform::TransformDialect::reportDuplicateTypeRegistration(118    StringRef mnemonic) {119  std::string buffer;120  llvm::raw_string_ostream msg(buffer);121  msg << "extensible dialect type '" << mnemonic122      << "' is already registered with a different implementation";123  llvm::report_fatal_error(StringRef(buffer));124}125 126void transform::TransformDialect::reportDuplicateOpRegistration(127    StringRef opName) {128  std::string buffer;129  llvm::raw_string_ostream msg(buffer);130  msg << "extensible dialect operation '" << opName131      << "' is already registered with a mismatching TypeID";132  llvm::report_fatal_error(StringRef(buffer));133}134 135LogicalResult transform::TransformDialect::verifyOperationAttribute(136    Operation *op, NamedAttribute attribute) {137  if (attribute.getName().getValue() == kWithNamedSequenceAttrName) {138    if (!op->hasTrait<OpTrait::SymbolTable>()) {139      return emitError(op->getLoc()) << attribute.getName()140                                     << " attribute can only be attached to "141                                        "operations with symbol tables";142    }143 144    // Pre-verify calls and callables because call graph construction below145    // assumes they are valid, but this verifier runs before verifying the146    // nested operations.147    WalkResult walkResult = op->walk([](Operation *nested) {148      if (!isa<CallableOpInterface, CallOpInterface>(nested))149        return WalkResult::advance();150 151      if (failed(verify(nested, /*verifyRecursively=*/false)))152        return WalkResult::interrupt();153      return WalkResult::advance();154    });155    if (walkResult.wasInterrupted())156      return failure();157 158    const mlir::CallGraph callgraph(op);159    for (auto scc = llvm::scc_begin(&callgraph); !scc.isAtEnd(); ++scc) {160      if (!scc.hasCycle())161        continue;162 163      // Need to check this here additionally because this verification may run164      // before we check the nested operations.165      if ((*scc->begin())->isExternal())166        return op->emitOpError() << "contains a call to an external operation, "167                                    "which is not allowed";168 169      Operation *first = (*scc->begin())->getCallableRegion()->getParentOp();170      InFlightDiagnostic diag = emitError(first->getLoc())171                                << "recursion not allowed in named sequences";172      for (auto it = std::next(scc->begin()); it != scc->end(); ++it) {173        // Need to check this here additionally because this verification may174        // run before we check the nested operations.175        if ((*it)->isExternal()) {176          return op->emitOpError() << "contains a call to an external "177                                      "operation, which is not allowed";178        }179 180        Operation *current = (*it)->getCallableRegion()->getParentOp();181        diag.attachNote(current->getLoc()) << "operation on recursion stack";182      }183      return diag;184    }185    return success();186  }187  if (attribute.getName().getValue() == kTargetTagAttrName) {188    if (!llvm::isa<StringAttr>(attribute.getValue())) {189      return op->emitError()190             << attribute.getName() << " attribute must be a string";191    }192    return success();193  }194  if (attribute.getName().getValue() == kArgConsumedAttrName ||195      attribute.getName().getValue() == kArgReadOnlyAttrName) {196    if (!llvm::isa<UnitAttr>(attribute.getValue())) {197      return op->emitError()198             << attribute.getName() << " must be a unit attribute";199    }200    return success();201  }202  if (attribute.getName().getValue() ==203      FindPayloadReplacementOpInterface::kSilenceTrackingFailuresAttrName) {204    if (!llvm::isa<UnitAttr>(attribute.getValue())) {205      return op->emitError()206             << attribute.getName() << " must be a unit attribute";207    }208    return success();209  }210  return emitError(op->getLoc())211         << "unknown attribute: " << attribute.getName();212}213