222 lines
8.9 KiB
C++
222 lines
8.9 KiB
C++
//===- DialectResourceBlobManager.h - Dialect Blob Management ---*- 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 defines utility classes for referencing and managing asm resource
|
|
// blobs. These classes are intended to more easily facilitate the sharing of
|
|
// large blobs, and their definition.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef MLIR_IR_DIALECTRESOURCEBLOBMANAGER_H
|
|
#define MLIR_IR_DIALECTRESOURCEBLOBMANAGER_H
|
|
|
|
#include "mlir/IR/AsmState.h"
|
|
#include "mlir/IR/OpImplementation.h"
|
|
#include "llvm/ADT/StringMap.h"
|
|
#include "llvm/ADT/Twine.h"
|
|
#include "llvm/Support/RWMutex.h"
|
|
#include "llvm/Support/SMLoc.h"
|
|
#include <optional>
|
|
|
|
namespace mlir {
|
|
//===----------------------------------------------------------------------===//
|
|
// DialectResourceBlobManager
|
|
//===---------------------------------------------------------------------===//
|
|
|
|
/// This class defines a manager for dialect resource blobs. Blobs are uniqued
|
|
/// by a given key, and represented using AsmResourceBlobs.
|
|
class DialectResourceBlobManager {
|
|
public:
|
|
/// The class represents an individual entry of a blob.
|
|
class BlobEntry {
|
|
public:
|
|
/// Return the key used to reference this blob.
|
|
StringRef getKey() const { return key; }
|
|
|
|
/// Return the blob owned by this entry if one has been initialized. Returns
|
|
/// nullptr otherwise.
|
|
const AsmResourceBlob *getBlob() const { return blob ? &*blob : nullptr; }
|
|
AsmResourceBlob *getBlob() { return blob ? &*blob : nullptr; }
|
|
|
|
/// Set the blob owned by this entry.
|
|
void setBlob(AsmResourceBlob &&newBlob) { blob = std::move(newBlob); }
|
|
|
|
private:
|
|
BlobEntry() = default;
|
|
BlobEntry(BlobEntry &&) = default;
|
|
BlobEntry &operator=(const BlobEntry &) = delete;
|
|
BlobEntry &operator=(BlobEntry &&) = delete;
|
|
|
|
/// Initialize this entry with the given key and blob.
|
|
void initialize(StringRef newKey, std::optional<AsmResourceBlob> newBlob) {
|
|
key = newKey;
|
|
blob = std::move(newBlob);
|
|
}
|
|
|
|
/// The key used for this blob.
|
|
StringRef key;
|
|
|
|
/// The blob that is referenced by this entry if it is valid.
|
|
std::optional<AsmResourceBlob> blob;
|
|
|
|
/// Allow access to the constructors.
|
|
friend DialectResourceBlobManager;
|
|
friend class llvm::StringMapEntryStorage<BlobEntry>;
|
|
};
|
|
|
|
/// Return the blob registered for the given name, or nullptr if no blob
|
|
/// is registered.
|
|
BlobEntry *lookup(StringRef name);
|
|
const BlobEntry *lookup(StringRef name) const {
|
|
return const_cast<DialectResourceBlobManager *>(this)->lookup(name);
|
|
}
|
|
|
|
/// Update the blob for the entry defined by the provided name. This method
|
|
/// asserts that an entry for the given name exists in the manager.
|
|
void update(StringRef name, AsmResourceBlob &&newBlob);
|
|
|
|
/// Insert a new entry with the provided name and optional blob data. The name
|
|
/// may be modified during insertion if another entry already exists with that
|
|
/// name. Returns the inserted entry.
|
|
BlobEntry &insert(StringRef name, std::optional<AsmResourceBlob> blob = {});
|
|
/// Insertion method that returns a dialect specific handle to the inserted
|
|
/// entry.
|
|
template <typename HandleT>
|
|
HandleT insert(typename HandleT::Dialect *dialect, StringRef name,
|
|
std::optional<AsmResourceBlob> blob = {}) {
|
|
BlobEntry &entry = insert(name, std::move(blob));
|
|
return HandleT(&entry, dialect);
|
|
}
|
|
|
|
/// Provide access to all the registered blobs via a callable. During access
|
|
/// the blob map is guaranteed to remain unchanged.
|
|
void getBlobMap(llvm::function_ref<void(const llvm::StringMap<BlobEntry> &)>
|
|
accessor) const;
|
|
|
|
private:
|
|
/// A mutex to protect access to the blob map.
|
|
mutable llvm::sys::SmartRWMutex<true> blobMapLock;
|
|
|
|
/// The internal map of tracked blobs. StringMap stores entries in distinct
|
|
/// allocations, so we can freely take references to the data without fear of
|
|
/// invalidation during additional insertion/deletion.
|
|
llvm::StringMap<BlobEntry> blobMap;
|
|
};
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// ResourceBlobManagerDialectInterface
|
|
//===---------------------------------------------------------------------===//
|
|
|
|
/// This class implements a dialect interface that provides common functionality
|
|
/// for interacting with a resource blob manager.
|
|
class ResourceBlobManagerDialectInterface
|
|
: public DialectInterface::Base<ResourceBlobManagerDialectInterface> {
|
|
public:
|
|
ResourceBlobManagerDialectInterface(Dialect *dialect)
|
|
: Base(dialect),
|
|
blobManager(std::make_shared<DialectResourceBlobManager>()) {}
|
|
|
|
/// Return the blob manager held by this interface.
|
|
DialectResourceBlobManager &getBlobManager() { return *blobManager; }
|
|
const DialectResourceBlobManager &getBlobManager() const {
|
|
return *blobManager;
|
|
}
|
|
|
|
/// Set the blob manager held by this interface.
|
|
void
|
|
setBlobManager(std::shared_ptr<DialectResourceBlobManager> newBlobManager) {
|
|
blobManager = std::move(newBlobManager);
|
|
}
|
|
|
|
private:
|
|
/// The blob manager owned by the dialect implementing this interface.
|
|
std::shared_ptr<DialectResourceBlobManager> blobManager;
|
|
};
|
|
|
|
/// This class provides a base class for dialects implementing the resource blob
|
|
/// interface. It provides several additional dialect specific utilities on top
|
|
/// of the generic interface. `HandleT` is the type of the handle used to
|
|
/// reference a resource blob.
|
|
template <typename HandleT>
|
|
class ResourceBlobManagerDialectInterfaceBase
|
|
: public ResourceBlobManagerDialectInterface {
|
|
public:
|
|
using ResourceBlobManagerDialectInterface::
|
|
ResourceBlobManagerDialectInterface;
|
|
|
|
/// Update the blob for the entry defined by the provided name. This method
|
|
/// asserts that an entry for the given name exists in the manager.
|
|
void update(StringRef name, AsmResourceBlob &&newBlob) {
|
|
getBlobManager().update(name, std::move(newBlob));
|
|
}
|
|
|
|
/// Insert a new resource blob entry with the provided name and optional blob
|
|
/// data. The name may be modified during insertion if another entry already
|
|
/// exists with that name. Returns a dialect specific handle to the inserted
|
|
/// entry.
|
|
HandleT insert(StringRef name, std::optional<AsmResourceBlob> blob = {}) {
|
|
return getBlobManager().template insert<HandleT>(
|
|
cast<typename HandleT::Dialect>(getDialect()), name, std::move(blob));
|
|
}
|
|
|
|
/// Build resources for each of the referenced blobs within this manager.
|
|
void buildResources(AsmResourceBuilder &provider,
|
|
ArrayRef<AsmDialectResourceHandle> referencedResources) {
|
|
for (const AsmDialectResourceHandle &handle : referencedResources) {
|
|
if (const auto *dialectHandle = dyn_cast<HandleT>(&handle)) {
|
|
if (auto *blob = dialectHandle->getBlob())
|
|
provider.buildBlob(dialectHandle->getKey(), *blob);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// DialectResourceBlobHandle
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// This class defines a dialect specific handle to a resource blob. These
|
|
/// handles utilize a StringRef for the internal key, and an AsmResourceBlob as
|
|
/// the underlying data.
|
|
template <typename DialectT>
|
|
struct DialectResourceBlobHandle
|
|
: public AsmDialectResourceHandleBase<DialectResourceBlobHandle<DialectT>,
|
|
DialectResourceBlobManager::BlobEntry,
|
|
DialectT> {
|
|
using AsmDialectResourceHandleBase<DialectResourceBlobHandle<DialectT>,
|
|
DialectResourceBlobManager::BlobEntry,
|
|
DialectT>::AsmDialectResourceHandleBase;
|
|
using ManagerInterface = ResourceBlobManagerDialectInterfaceBase<
|
|
DialectResourceBlobHandle<DialectT>>;
|
|
|
|
/// Return the human readable string key for this handle.
|
|
StringRef getKey() const { return this->getResource()->getKey(); }
|
|
|
|
/// Return the blob referenced by this handle if the underlying resource has
|
|
/// been initialized. Returns nullptr otherwise.
|
|
AsmResourceBlob *getBlob() { return this->getResource()->getBlob(); }
|
|
const AsmResourceBlob *getBlob() const {
|
|
return this->getResource()->getBlob();
|
|
}
|
|
|
|
/// Get the interface for the dialect that owns handles of this type. Asserts
|
|
/// that the dialect is registered.
|
|
static ManagerInterface &getManagerInterface(MLIRContext *ctx) {
|
|
auto *dialect = ctx->getOrLoadDialect<DialectT>();
|
|
assert(dialect && "dialect not registered");
|
|
|
|
auto *iface = dialect->template getRegisteredInterface<ManagerInterface>();
|
|
assert(iface && "dialect doesn't provide the blob manager interface?");
|
|
return *iface;
|
|
}
|
|
};
|
|
|
|
} // namespace mlir
|
|
|
|
#endif // MLIR_IR_DIALECTRESOURCEBLOBMANAGER_H
|