//===- IRDLTraits.h - IRDL traits definition ---------------------*- C++ //-*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file declares the traits used by the IR Definition Language dialect. // //===----------------------------------------------------------------------===// #ifndef MLIR_DIALECT_IRDL_IR_IRDLTRAITS_H_ #define MLIR_DIALECT_IRDL_IR_IRDLTRAITS_H_ #include "mlir/IR/OpDefinition.h" #include "llvm/Support/Casting.h" namespace mlir { namespace OpTrait { /// Characterize operations that have at most a single operation of certain /// types in their region. /// This check is only done on the children that are immediate children of the /// operation, and does not recurse into the children's regions. /// This trait expects the Op to satisfy the `OneRegion` trait. template class AtMostOneChildOf { public: template class Impl : public TraitBase::Impl> { public: static LogicalResult verifyTrait(Operation *op) { static_assert( ConcreteType::template hasTrait<::mlir::OpTrait::OneRegion>(), "expected operation to have a single region"); static_assert(sizeof...(ChildOps) > 0, "expected at least one child operation type"); // Contains `true` if the corresponding child op has been seen. bool satisfiedOps[sizeof...(ChildOps)] = {}; for (Operation &child : cast(op).getOps()) { int childOpIndex = 0; if (((isa(child) ? false : (++childOpIndex, true)) && ...)) continue; // Check that the operation has not been seen before. if (satisfiedOps[childOpIndex]) return op->emitError() << "failed to verify AtMostOneChildOf trait: the operation " "contains at least two operations of type " << child.getName(); // Mark the operation as seen. satisfiedOps[childOpIndex] = true; } return success(); } /// Get the unique operation of a specific op that is in the operation /// region. template std::enable_if_t...>::value, std::optional> getOp() { auto ops = cast(this->getOperation()).template getOps(); if (ops.empty()) return {}; return {*ops.begin()}; } }; }; } // namespace OpTrait } // namespace mlir #endif // MLIR_DIALECT_IRDL_IR_IRDLTRAITS_H_