Files
gps/tools/local/circt/include/llvm/CAS/CASReference.h
T
2026-07-12 11:01:51 +03:00

171 lines
5.4 KiB
C++

//===- llvm/CAS/CASReference.h ----------------------------------*- 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
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CAS_CASREFERENCE_H
#define LLVM_CAS_CASREFERENCE_H
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMapInfo.h"
#include "llvm/ADT/StringRef.h"
namespace llvm {
class raw_ostream;
namespace cas {
class ObjectStore;
class ObjectHandle;
class ObjectRef;
/// Base class for references to things in \a ObjectStore.
class ReferenceBase {
protected:
static constexpr uint64_t getDenseMapEmptyRef() { return -1ULL; }
static constexpr uint64_t getDenseMapTombstoneRef() { return -2ULL; }
public:
/// Get an internal reference.
uint64_t getInternalRef(const ObjectStore &ExpectedCAS) const {
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
assert(CAS == &ExpectedCAS && "Extracting reference for the wrong CAS");
#endif
return InternalRef;
}
/// Helper functions for DenseMapInfo.
unsigned getDenseMapHash() const {
return static_cast<unsigned>(llvm::hash_value(InternalRef));
}
bool isDenseMapEmpty() const { return InternalRef == getDenseMapEmptyRef(); }
bool isDenseMapTombstone() const {
return InternalRef == getDenseMapTombstoneRef();
}
bool isDenseMapSentinel() const {
return isDenseMapEmpty() || isDenseMapTombstone();
}
protected:
void print(raw_ostream &OS, const ObjectHandle &This) const;
void print(raw_ostream &OS, const ObjectRef &This) const;
bool hasSameInternalRef(const ReferenceBase &RHS) const {
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
assert(
(isDenseMapSentinel() || RHS.isDenseMapSentinel() || CAS == RHS.CAS) &&
"Cannot compare across CAS instances");
#endif
return InternalRef == RHS.InternalRef;
}
protected:
friend class ObjectStore;
ReferenceBase(const ObjectStore *CAS, uint64_t InternalRef, bool IsHandle)
: InternalRef(InternalRef) {
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
this->CAS = CAS;
#endif
assert(InternalRef != getDenseMapEmptyRef() && "Reserved for DenseMapInfo");
assert(InternalRef != getDenseMapTombstoneRef() &&
"Reserved for DenseMapInfo");
}
private:
uint64_t InternalRef;
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
const ObjectStore *CAS = nullptr;
#endif
};
/// Reference to an object in an \a ObjectStore instance.
///
/// If you have an ObjectRef, you know the object exists, and you can point at
/// it from new nodes with \a ObjectStore::store(), but you don't know anything
/// about it. "Loading" the object is a separate step that may not have
/// happened yet, and which can fail (due to filesystem corruption) or
/// introduce latency (if downloading from a remote store).
///
/// \a ObjectStore::store() takes a list of these, and these are returned by \a
/// ObjectStore::forEachRef() and \a ObjectStore::readRef(), which are accessors
/// for nodes, and \a ObjectStore::getReference().
///
/// \a ObjectStore::load() will load the referenced object, and returns \a
/// ObjectHandle, a variant that knows what kind of entity it is. \a
/// ObjectStore::getReferenceKind() can expect the type of reference without
/// asking for unloaded objects to be loaded.
class ObjectRef : public ReferenceBase {
public:
friend bool operator==(const ObjectRef &LHS, const ObjectRef &RHS) {
return LHS.hasSameInternalRef(RHS);
}
friend bool operator!=(const ObjectRef &LHS, const ObjectRef &RHS) {
return !(LHS == RHS);
}
/// Print internal ref and/or CASID. Only suitable for debugging.
void print(raw_ostream &OS) const { return ReferenceBase::print(OS, *this); }
LLVM_DUMP_METHOD void dump() const;
private:
friend class ObjectStore;
friend class ReferenceBase;
using ReferenceBase::ReferenceBase;
ObjectRef(const ObjectStore &CAS, uint64_t InternalRef)
: ReferenceBase(&CAS, InternalRef, /*IsHandle=*/false) {
assert(InternalRef != -1ULL && "Reserved for DenseMapInfo");
assert(InternalRef != -2ULL && "Reserved for DenseMapInfo");
}
explicit ObjectRef(ReferenceBase) = delete;
};
/// Handle to a loaded object in a \a ObjectStore instance.
///
/// ObjectHandle encapulates a *loaded* object in the CAS. You need one
/// of these to inspect the content of an object: to look at its stored
/// data and references.
class ObjectHandle : public ReferenceBase {
public:
friend bool operator==(const ObjectHandle &LHS, const ObjectHandle &RHS) {
return LHS.hasSameInternalRef(RHS);
}
friend bool operator!=(const ObjectHandle &LHS, const ObjectHandle &RHS) {
return !(LHS == RHS);
}
/// Print internal ref and/or CASID. Only suitable for debugging.
void print(raw_ostream &OS) const { return ReferenceBase::print(OS, *this); }
LLVM_DUMP_METHOD void dump() const;
private:
friend class ObjectStore;
friend class ReferenceBase;
using ReferenceBase::ReferenceBase;
explicit ObjectHandle(ReferenceBase) = delete;
ObjectHandle(const ObjectStore &CAS, uint64_t InternalRef)
: ReferenceBase(&CAS, InternalRef, /*IsHandle=*/true) {}
};
} // namespace cas
template <> struct DenseMapInfo<cas::ObjectRef> {
static unsigned getHashValue(cas::ObjectRef Ref) {
return Ref.getDenseMapHash();
}
static bool isEqual(cas::ObjectRef LHS, cas::ObjectRef RHS) {
return LHS == RHS;
}
};
} // namespace llvm
#endif // LLVM_CAS_CASREFERENCE_H