204 lines
8.4 KiB
C++
204 lines
8.4 KiB
C++
//===- 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 T>
|
|
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<StringRef> &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<StringRef> 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 <typename CallableT,
|
|
std::enable_if_t<std::is_convertible_v<
|
|
CallableT, std::function<LogicalResult(
|
|
T, std::optional<StringRef> &,
|
|
DialectBytecodeWriter &)>>,
|
|
bool> = true>
|
|
static std::unique_ptr<AttrTypeBytecodeWriter<T>>
|
|
fromCallable(CallableT &&writeFn) {
|
|
struct Processor : public AttrTypeBytecodeWriter<T> {
|
|
Processor(CallableT &&writeFn)
|
|
: AttrTypeBytecodeWriter(), writeFn(std::move(writeFn)) {}
|
|
LogicalResult write(T entry, std::optional<StringRef> &name,
|
|
DialectBytecodeWriter &writer) override {
|
|
return writeFn(entry, name, writer);
|
|
}
|
|
|
|
std::decay_t<CallableT> writeFn;
|
|
};
|
|
return std::make_unique<Processor>(std::forward<CallableT>(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<std::unique_ptr<DialectVersion>> &
|
|
getDialectVersionMap() const;
|
|
|
|
/// Set a given dialect version to emit on the map.
|
|
template <class T>
|
|
void setDialectVersion(std::unique_ptr<DialectVersion> dialectVersion) const {
|
|
return setDialectVersion(T::getDialectNamespace(),
|
|
std::move(dialectVersion));
|
|
}
|
|
void setDialectVersion(StringRef dialectName,
|
|
std::unique_ptr<DialectVersion> dialectVersion) const;
|
|
|
|
//===--------------------------------------------------------------------===//
|
|
// Types and Attributes encoding
|
|
//===--------------------------------------------------------------------===//
|
|
|
|
/// Retrieve the callbacks.
|
|
ArrayRef<std::unique_ptr<AttrTypeBytecodeWriter<Attribute>>>
|
|
getAttributeWriterCallbacks() const;
|
|
ArrayRef<std::unique_ptr<AttrTypeBytecodeWriter<Type>>>
|
|
getTypeWriterCallbacks() const;
|
|
|
|
/// Attach a custom bytecode printer callback to the configuration for the
|
|
/// emission of custom type/attributes encodings.
|
|
void attachAttributeCallback(
|
|
std::unique_ptr<AttrTypeBytecodeWriter<Attribute>> callback);
|
|
void
|
|
attachTypeCallback(std::unique_ptr<AttrTypeBytecodeWriter<Type>> callback);
|
|
|
|
/// Attach a custom bytecode printer callback to the configuration for the
|
|
/// emission of custom type/attributes encodings.
|
|
template <typename CallableT>
|
|
std::enable_if_t<std::is_convertible_v<
|
|
CallableT,
|
|
std::function<LogicalResult(Attribute, std::optional<StringRef> &,
|
|
DialectBytecodeWriter &)>>>
|
|
attachAttributeCallback(CallableT &&emitFn) {
|
|
attachAttributeCallback(AttrTypeBytecodeWriter<Attribute>::fromCallable(
|
|
std::forward<CallableT>(emitFn)));
|
|
}
|
|
template <typename CallableT>
|
|
std::enable_if_t<std::is_convertible_v<
|
|
CallableT, std::function<LogicalResult(Type, std::optional<StringRef> &,
|
|
DialectBytecodeWriter &)>>>
|
|
attachTypeCallback(CallableT &&emitFn) {
|
|
attachTypeCallback(AttrTypeBytecodeWriter<Type>::fromCallable(
|
|
std::forward<CallableT>(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<AsmResourcePrinter> printer);
|
|
|
|
/// Attach an resource printer, in the form of a callable, to the
|
|
/// configuration.
|
|
template <typename CallableT>
|
|
std::enable_if_t<std::is_convertible<
|
|
CallableT, function_ref<void(Operation *, AsmResourceBuilder &)>>::value>
|
|
attachResourcePrinter(StringRef name, CallableT &&printFn) {
|
|
attachResourcePrinter(AsmResourcePrinter::fromCallable(
|
|
name, std::forward<CallableT>(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> 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
|