llvm/mlir/include/mlir/IR/OpImplementation.h

//===- OpImplementation.h - Classes for implementing Op types ---*- 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 classes used by the implementation details of Op types.
//
//===----------------------------------------------------------------------===//

#ifndef MLIR_IR_OPIMPLEMENTATION_H
#define MLIR_IR_OPIMPLEMENTATION_H

#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/DialectInterface.h"
#include "mlir/IR/OpDefinition.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/SMLoc.h"
#include <optional>

namespace mlir {
class AsmParsedResourceEntry;
class AsmResourceBuilder;
class Builder;

//===----------------------------------------------------------------------===//
// AsmDialectResourceHandle
//===----------------------------------------------------------------------===//

/// This class represents an opaque handle to a dialect resource entry.
class AsmDialectResourceHandle {};

/// This class represents a CRTP base class for dialect resource handles. It
/// abstracts away various utilities necessary for defined derived resource
/// handles.
template <typename DerivedT, typename ResourceT, typename DialectT>
class AsmDialectResourceHandleBase : public AsmDialectResourceHandle {};

inline llvm::hash_code hash_value(const AsmDialectResourceHandle &param) {}

//===----------------------------------------------------------------------===//
// AsmPrinter
//===----------------------------------------------------------------------===//

/// This base class exposes generic asm printer hooks, usable across the various
/// derived printers.
class AsmPrinter {};

template <typename AsmPrinterT>
inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
                        AsmPrinterT &>
operator<<(AsmPrinterT &p, Type type) {}

template <typename AsmPrinterT>
inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
                        AsmPrinterT &>
operator<<(AsmPrinterT &p, Attribute attr) {}

template <typename AsmPrinterT>
inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
                        AsmPrinterT &>
operator<<(AsmPrinterT &p, const APFloat &value) {}
template <typename AsmPrinterT>
inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
                        AsmPrinterT &>
operator<<(AsmPrinterT &p, float value) {}
template <typename AsmPrinterT>
inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
                        AsmPrinterT &>
operator<<(AsmPrinterT &p, double value) {}

// Support printing anything that isn't convertible to one of the other
// streamable types, even if it isn't exactly one of them. For example, we want
// to print FunctionType with the Type version above, not have it match this.
template <typename AsmPrinterT, typename T,
          std::enable_if_t<!std::is_convertible<T &, Value &>::value &&
                               !std::is_convertible<T &, Type &>::value &&
                               !std::is_convertible<T &, Attribute &>::value &&
                               !std::is_convertible<T &, ValueRange>::value &&
                               !std::is_convertible<T &, APFloat &>::value &&
                               !llvm::is_one_of<T, bool, float, double>::value,
                           T> * = nullptr>
inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
                        AsmPrinterT &>
operator<<(AsmPrinterT &p, const T &other) {}

template <typename AsmPrinterT>
inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
                        AsmPrinterT &>
operator<<(AsmPrinterT &p, bool value) {}

template <typename AsmPrinterT, typename ValueRangeT>
inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
                        AsmPrinterT &>
operator<<(AsmPrinterT &p, const ValueTypeRange<ValueRangeT> &types) {}

template <typename AsmPrinterT>
inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
                        AsmPrinterT &>
operator<<(AsmPrinterT &p, const TypeRange &types) {}

// Prevent matching the TypeRange version above for ValueRange
// printing through base AsmPrinter. This is needed so that the
// ValueRange printing behaviour does not change from printing
// the SSA values to printing the types for the operands when
// using AsmPrinter instead of OpAsmPrinter.
template <typename AsmPrinterT, typename T>
inline std::enable_if_t<std::is_same<AsmPrinter, AsmPrinterT>::value &&
                            std::is_convertible<T &, ValueRange>::value,
                        AsmPrinterT &>
operator<<(AsmPrinterT &p, const T &other) = delete;

template <typename AsmPrinterT, typename ElementT>
inline std::enable_if_t<std::is_base_of<AsmPrinter, AsmPrinterT>::value,
                        AsmPrinterT &>
operator<<(AsmPrinterT &p, ArrayRef<ElementT> types) {}

//===----------------------------------------------------------------------===//
// OpAsmPrinter
//===----------------------------------------------------------------------===//

/// This is a pure-virtual base class that exposes the asmprinter hooks
/// necessary to implement a custom print() method.
class OpAsmPrinter : public AsmPrinter {};

// Make the implementations convenient to use.
inline OpAsmPrinter &operator<<(OpAsmPrinter &p, Value value) {}

template <typename T,
          std::enable_if_t<std::is_convertible<T &, ValueRange>::value &&
                               !std::is_convertible<T &, Value &>::value,
                           T> * = nullptr>
inline OpAsmPrinter &operator<<(OpAsmPrinter &p, const T &values) {}

inline OpAsmPrinter &operator<<(OpAsmPrinter &p, Block *value) {}

//===----------------------------------------------------------------------===//
// AsmParser
//===----------------------------------------------------------------------===//

/// This base class exposes generic asm parser hooks, usable across the various
/// derived parsers.
class AsmParser {};

//===----------------------------------------------------------------------===//
// OpAsmParser
//===----------------------------------------------------------------------===//

/// The OpAsmParser has methods for interacting with the asm parser: parsing
/// things from it, emitting errors etc.  It has an intentionally high-level API
/// that is designed to reduce/constrain syntax innovation in individual
/// operations.
///
/// For example, consider an op like this:
///
///    %x = load %p[%1, %2] : memref<...>
///
/// The "%x = load" tokens are already parsed and therefore invisible to the
/// custom op parser.  This can be supported by calling `parseOperandList` to
/// parse the %p, then calling `parseOperandList` with a `SquareDelimiter` to
/// parse the indices, then calling `parseColonTypeList` to parse the result
/// type.
///
class OpAsmParser : public AsmParser {};

//===--------------------------------------------------------------------===//
// Dialect OpAsm interface.
//===--------------------------------------------------------------------===//

/// A functor used to set the name of the start of a result group of an
/// operation. See 'getAsmResultNames' below for more details.
OpAsmSetValueNameFn;

/// A functor used to set the name of blocks in regions directly nested under
/// an operation.
OpAsmSetBlockNameFn;

class OpAsmDialectInterface
    : public DialectInterface::Base<OpAsmDialectInterface> {};

//===--------------------------------------------------------------------===//
// Custom printers and parsers.
//===--------------------------------------------------------------------===//

// Handles custom<DimensionList>(...) in TableGen.
void printDimensionList(OpAsmPrinter &printer, Operation *op,
                        ArrayRef<int64_t> dimensions);
ParseResult parseDimensionList(OpAsmParser &parser,
                               DenseI64ArrayAttr &dimensions);

} // namespace mlir

//===--------------------------------------------------------------------===//
// Operation OpAsm interface.
//===--------------------------------------------------------------------===//

/// The OpAsmOpInterface, see OpAsmInterface.td for more details.
#include "mlir/IR/OpAsmInterface.h.inc"

namespace llvm {
template <>
struct DenseMapInfo<mlir::AsmDialectResourceHandle> {};
} // namespace llvm

#endif