//===- BytecodeWriter.h - MLIR Bytecode Writer ------------------*- 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 header defines interfaces to write MLIR bytecode files/streams. // //===----------------------------------------------------------------------===// #ifndef MLIR_BYTECODE_BYTECODEWRITER_H #define MLIR_BYTECODE_BYTECODEWRITER_H #include "mlir/IR/AsmState.h" #include "llvm/Config/llvm-config.h" // for LLVM_VERSION_STRING namespace mlir { class DialectBytecodeWriter; class DialectVersion; class Operation; /// A class to interact with the attributes and types printer when emitting MLIR /// bytecode. template class AttrTypeBytecodeWriter { public: AttrTypeBytecodeWriter() = default; virtual ~AttrTypeBytecodeWriter() = default; /// Callback writer API used in IRNumbering, where groups are created and /// type/attribute components are numbered. At this stage, writer is expected /// to be a `NumberingDialectWriter`. virtual LogicalResult write(T entry, std::optional &name, DialectBytecodeWriter &writer) = 0; /// Callback writer API used in BytecodeWriter, where groups are created and /// type/attribute components are numbered. Here, DialectBytecodeWriter is /// expected to be an actual writer. The optional stringref specified by /// the user is ignored, since the group was already specified when numbering /// the IR. LogicalResult write(T entry, DialectBytecodeWriter &writer) { std::optional dummy; return write(entry, dummy, writer); } /// Return an Attribute/Type printer implemented via the given callable, whose /// form should match that of the `write` function above. template &, DialectBytecodeWriter &)>>, bool> = true> static std::unique_ptr> fromCallable(CallableT &&writeFn) { struct Processor : public AttrTypeBytecodeWriter { Processor(CallableT &&writeFn) : AttrTypeBytecodeWriter(), writeFn(std::move(writeFn)) {} LogicalResult write(T entry, std::optional &name, DialectBytecodeWriter &writer) override { return writeFn(entry, name, writer); } std::decay_t writeFn; }; return std::make_unique(std::forward(writeFn)); } }; /// This class contains the configuration used for the bytecode writer. It /// controls various aspects of bytecode generation, and contains all of the /// various bytecode writer hooks. class BytecodeWriterConfig { public: /// `producer` is an optional string that can be used to identify the producer /// of the bytecode when reading. It has no functional effect on the bytecode /// serialization. BytecodeWriterConfig(StringRef producer = "MLIR" LLVM_VERSION_STRING); /// `map` is a fallback resource map, which when provided will attach resource /// printers for the fallback resources within the map. BytecodeWriterConfig(FallbackAsmResourceMap &map, StringRef producer = "MLIR" LLVM_VERSION_STRING); BytecodeWriterConfig(BytecodeWriterConfig &&); ~BytecodeWriterConfig(); /// An internal implementation class that contains the state of the /// configuration. struct Impl; /// Return an instance of the internal implementation. const Impl &getImpl() const { return *impl; } /// Set the desired bytecode version to emit. This method does not validate /// the desired version. The bytecode writer entry point will return failure /// if it cannot emit the desired version. void setDesiredBytecodeVersion(int64_t bytecodeVersion); /// Get the set desired bytecode version to emit. int64_t getDesiredBytecodeVersion() const; /// A map containing the dialect versions to emit. llvm::StringMap> & getDialectVersionMap() const; /// Set a given dialect version to emit on the map. template void setDialectVersion(std::unique_ptr dialectVersion) const { return setDialectVersion(T::getDialectNamespace(), std::move(dialectVersion)); } void setDialectVersion(StringRef dialectName, std::unique_ptr dialectVersion) const; //===--------------------------------------------------------------------===// // Types and Attributes encoding //===--------------------------------------------------------------------===// /// Retrieve the callbacks. ArrayRef>> getAttributeWriterCallbacks() const; ArrayRef>> getTypeWriterCallbacks() const; /// Attach a custom bytecode printer callback to the configuration for the /// emission of custom type/attributes encodings. void attachAttributeCallback( std::unique_ptr> callback); void attachTypeCallback(std::unique_ptr> callback); /// Attach a custom bytecode printer callback to the configuration for the /// emission of custom type/attributes encodings. template std::enable_if_t &, DialectBytecodeWriter &)>>> attachAttributeCallback(CallableT &&emitFn) { attachAttributeCallback(AttrTypeBytecodeWriter::fromCallable( std::forward(emitFn))); } template std::enable_if_t &, DialectBytecodeWriter &)>>> attachTypeCallback(CallableT &&emitFn) { attachTypeCallback(AttrTypeBytecodeWriter::fromCallable( std::forward(emitFn))); } //===--------------------------------------------------------------------===// // Resources //===--------------------------------------------------------------------===// /// Set a boolean flag to skip emission of resources into the bytecode file. void setElideResourceDataFlag(bool shouldElideResourceData = true); /// Attach the given resource printer to the writer configuration. void attachResourcePrinter(std::unique_ptr printer); /// Attach an resource printer, in the form of a callable, to the /// configuration. template std::enable_if_t>::value> attachResourcePrinter(StringRef name, CallableT &&printFn) { attachResourcePrinter(AsmResourcePrinter::fromCallable( name, std::forward(printFn))); } /// Attach resource printers to the AsmState for the fallback resources /// in the given map. void attachFallbackResourcePrinter(FallbackAsmResourceMap &map) { for (auto &printer : map.getPrinters()) attachResourcePrinter(std::move(printer)); } /// Set a boolean flag to skip emission of unique locations into the bytecode /// file. When enabled, all locations are mapped to UnknownLoc during /// numbering. void setElideLocations(bool shouldElideLocations = true); bool shouldElideLocations() const; private: /// A pointer to allocated storage for the impl state. std::unique_ptr impl; }; //===----------------------------------------------------------------------===// // Entry Points //===----------------------------------------------------------------------===// /// Write the bytecode for the given operation to the provided output stream. /// For streams where it matters, the given stream should be in "binary" mode. /// It only ever fails if setDesiredByteCodeVersion can't be honored. LogicalResult writeBytecodeToFile(Operation *op, raw_ostream &os, const BytecodeWriterConfig &config = {}); } // namespace mlir #endif // MLIR_BYTECODE_BYTECODEWRITER_H