34 void printIDImpl(raw_ostream &OS,
const CASID &ID)
const final;
36 StringRef getHashSchemaIdentifier()
const final {
return SchemaName; }
38 static Expected<std::shared_ptr<PluginCASContext>>
39 create(StringRef PluginPath, StringRef OnDiskPath,
40 ArrayRef<std::pair<std::string, std::string>> PluginArgs);
42 ~PluginCASContext() { Functions.cas_dispose(c_cas); }
44 llcas_functions_t Functions{};
46 std::string SchemaName;
48 static Error errorAndDispose(
char *c_err,
const llcas_functions_t &Funcs) {
54 Error errorAndDispose(
char *c_err)
const {
55 return errorAndDispose(c_err, Functions);
62 ArrayRef<uint8_t> Hash =
ID.getHash();
63 char *c_printed_id =
nullptr;
64 char *c_err =
nullptr;
65 if (Functions.
digest_print(c_cas, llcas_digest_t{Hash.data(), Hash.size()},
66 &c_printed_id, &c_err))
72Expected<std::shared_ptr<PluginCASContext>> PluginCASContext::create(
73 StringRef PluginPath, StringRef OnDiskPath,
74 ArrayRef<std::pair<std::string, std::string>> PluginArgs) {
81 SmallString<256> PathBuf = PluginPath;
83 sys::DynamicLibrary
Lib =
88 llcas_functions_t Functions{};
90#define CASPLUGINAPI_FUNCTION(name, required) \
91 if (!(Functions.name = (decltype(llcas_functions_t::name)) \
92 Lib.getAddressOfSymbol("llcas_" #name))) { \
94 return reportError("failed symbol 'llcas_" #name "' lookup"); \
96#include "PluginAPI_functions.def"
97#undef CASPLUGINAPI_FUNCTION
104 SmallString<256> OnDiskPathBuf = OnDiskPath;
106 for (
const auto &Pair : PluginArgs) {
107 char *c_err =
nullptr;
109 Pair.second.c_str(), &c_err))
110 return errorAndDispose(c_err, Functions);
113 char *c_err =
nullptr;
116 return errorAndDispose(c_err, Functions);
119 std::string SchemaName = c_schema;
122 auto Ctx = std::make_shared<PluginCASContext>();
123 Ctx->Functions = Functions;
125 Ctx->SchemaName = std::move(SchemaName);
135class PluginObjectStore :
public ObjectStore {
137 Expected<CASID> parseID(StringRef ID)
final;
139 ArrayRef<char>
Data)
final;
140 Expected<ObjectRef> storeFromFile(StringRef Path)
final;
141 Error exportDataToFile(ObjectHandle Node, StringRef Path)
const final;
142 CASID getID(ObjectRef
Ref)
const final;
143 std::optional<ObjectRef> getReference(
const CASID &ID)
const final;
144 Expected<bool> isMaterialized(ObjectRef
Ref)
const final;
145 Expected<std::optional<ObjectHandle>> loadIfExists(ObjectRef
Ref)
final;
146 uint64_t
getDataSize(ObjectHandle Node)
const final;
147 Error forEachRef(ObjectHandle Node,
148 function_ref<
Error(ObjectRef)> Callback)
const final;
149 ObjectRef readRef(ObjectHandle Node,
size_t I)
const final;
150 size_t getNumRefs(ObjectHandle Node)
const final;
151 ArrayRef<char> getData(ObjectHandle Node,
152 bool RequiresNullTerminator =
false)
const final;
153 std::unique_ptr<MemoryBuffer>
154 getStandaloneMemoryBufferImpl(ObjectHandle Node, StringRef Name,
155 bool RequiresNullTerminator) final;
164 Expected<std::optional<uint64_t>> getStorageSize()
const final;
165 Error pruneStorageData() final;
167 PluginObjectStore(std::shared_ptr<PluginCASContext>);
170 ObjectRef makeRef(uint64_t InternalRef)
const {
171 return makeObjectRef(InternalRef);
174 std::shared_ptr<PluginCASContext> Ctx;
179Expected<CASID> PluginObjectStore::parseID(StringRef ID) {
181 SmallString<148> IDBuf(ID);
184 auto parseDigest = [&]() -> Expected<unsigned> {
185 char *c_err =
nullptr;
186 unsigned NumBytes = Ctx->Functions.digest_parse(
187 Ctx->c_cas, IDBuf.c_str(), BytesBuf.data(), BytesBuf.size(), &c_err);
189 return Ctx->errorAndDispose(c_err);
193 Expected<unsigned> NumBytes = parseDigest();
197 if (*NumBytes > BytesBuf.size()) {
198 BytesBuf.resize(*NumBytes);
199 NumBytes = parseDigest();
202 assert(*NumBytes == BytesBuf.size());
204 BytesBuf.truncate(*NumBytes);
211 ArrayRef<char>
Data) {
214 for (ObjectRef
Ref : Refs) {
215 c_ids.
push_back(llcas_objectid_t{
Ref.getInternalRef(*
this)});
218 llcas_objectid_t c_stored_id;
219 char *c_err =
nullptr;
220 if (Ctx->Functions.cas_store_object(
221 Ctx->c_cas, llcas_data_t{Data.data(), Data.size()}, c_ids.
data(),
222 c_ids.
size(), &c_stored_id, &c_err))
223 return Ctx->errorAndDispose(c_err);
225 return makeObjectRef(c_stored_id.
opaque);
228Expected<ObjectRef> PluginObjectStore::storeFromFile(StringRef Path) {
229 if (!Ctx->Functions.cas_store_from_filepath)
232 llcas_objectid_t c_stored_id;
233 char *c_err =
nullptr;
234 std::string PathStr =
Path.str();
235 if (Ctx->Functions.cas_store_from_filepath(Ctx->c_cas, PathStr.c_str(),
236 &c_stored_id, &c_err))
237 return Ctx->errorAndDispose(c_err);
239 return makeObjectRef(c_stored_id.
opaque);
242Error PluginObjectStore::exportDataToFile(ObjectHandle Node,
243 StringRef Path)
const {
244 if (!Ctx->Functions.loaded_object_export_data_to_filepath)
247 char *c_err =
nullptr;
248 std::string PathStr =
Path.str();
249 if (Ctx->Functions.loaded_object_export_data_to_filepath(
250 Ctx->c_cas, llcas_loaded_object_t{Node.getInternalRef(*this)},
251 PathStr.c_str(), &c_err))
252 return Ctx->errorAndDispose(c_err);
261CASID PluginObjectStore::getID(ObjectRef
Ref)
const {
262 llcas_objectid_t c_id{
Ref.getInternalRef(*
this)};
263 llcas_digest_t c_digest =
264 Ctx->Functions.objectid_get_digest(Ctx->c_cas, c_id);
268std::optional<ObjectRef>
269PluginObjectStore::getReference(
const CASID &ID)
const {
270 ArrayRef<uint8_t> Hash =
ID.getHash();
271 llcas_objectid_t c_id;
272 char *c_err =
nullptr;
273 if (Ctx->Functions.cas_get_objectid(
274 Ctx->c_cas, llcas_digest_t{Hash.data(), Hash.size()}, &c_id, &c_err))
277 return makeObjectRef(c_id.
opaque);
280Expected<bool> PluginObjectStore::isMaterialized(ObjectRef
Ref)
const {
281 llcas_objectid_t c_id{
Ref.getInternalRef(*
this)};
282 char *c_err =
nullptr;
284 Ctx->c_cas, c_id,
false, &c_err);
291 return Ctx->errorAndDispose(c_err);
296Expected<std::optional<ObjectHandle>>
297PluginObjectStore::loadIfExists(ObjectRef
Ref) {
298 llcas_objectid_t c_id{
Ref.getInternalRef(*
this)};
299 llcas_loaded_object_t c_obj;
300 char *c_err =
nullptr;
302 Ctx->Functions.cas_load_object(Ctx->c_cas, c_id, &c_obj, &c_err);
305 return makeObjectHandle(c_obj.
opaque);
309 return Ctx->errorAndDispose(c_err);
316class ObjectRefsWrapper {
318 ObjectRefsWrapper(
const ObjectHandle &Node,
const PluginObjectStore &
Store)
320 llcas_loaded_object_t c_obj{
Node.getInternalRef(
Store)};
324 size_t size()
const {
328 ObjectRef operator[](
size_t I)
const {
329 llcas_objectid_t c_id =
335 const PluginObjectStore &
Store;
336 PluginCASContext &Ctx;
337 llcas_object_refs_t c_refs;
343Error PluginObjectStore::forEachRef(
344 ObjectHandle Node, function_ref<
Error(ObjectRef)> Callback)
const {
345 ObjectRefsWrapper Refs(Node, *
this);
346 for (
unsigned I = 0,
E = Refs.size();
I !=
E; ++
I) {
353ObjectRef PluginObjectStore::readRef(ObjectHandle Node,
size_t I)
const {
354 ObjectRefsWrapper Refs(Node, *
this);
358size_t PluginObjectStore::getNumRefs(ObjectHandle Node)
const {
359 ObjectRefsWrapper Refs(Node, *
this);
365uint64_t PluginObjectStore::getDataSize(ObjectHandle Node)
const {
366 ArrayRef<char>
Data = getData(Node);
370ArrayRef<char> PluginObjectStore::getData(ObjectHandle Node,
371 bool RequiresNullTerminator)
const {
374 llcas_data_t c_data = Ctx->Functions.loaded_object_get_data(
375 Ctx->c_cas, llcas_loaded_object_t{Node.getInternalRef(*this)});
383class PluginStandaloneMemoryBuffer final :
public MemoryBuffer {
385 using DisposeFn = void (*)(llcas_data_t);
387 PluginStandaloneMemoryBuffer(llcas_data_t
Data, StringRef Name,
390 const char *
Start =
static_cast<const char *
>(
Data.data);
391 init(Start, Start +
Data.size,
true);
394 ~PluginStandaloneMemoryBuffer()
override { Dispose(
Data); }
396 StringRef getBufferIdentifier()
const final {
return Name; }
398 BufferKind getBufferKind()
const final {
return MemoryBuffer_Malloc; }
407std::unique_ptr<MemoryBuffer> PluginObjectStore::getStandaloneMemoryBufferImpl(
408 ObjectHandle Node, StringRef Name,
bool RequiresNullTerminator) {
411 if (!Ctx->Functions.loaded_object_get_standalone_data ||
412 !Ctx->Functions.standalone_data_dispose)
414 RequiresNullTerminator);
416 llcas_data_t c_data = Ctx->Functions.loaded_object_get_standalone_data(
417 Ctx->c_cas, llcas_loaded_object_t{Node.getInternalRef(*this)});
420 RequiresNullTerminator);
422 return std::make_unique<PluginStandaloneMemoryBuffer>(
423 c_data, Name, Ctx->Functions.standalone_data_dispose);
426Error PluginObjectStore::setSizeLimit(std::optional<uint64_t>
SizeLimit) {
427 if (Ctx->Functions.cas_set_ondisk_size_limit) {
428 char *c_err =
nullptr;
429 if (Ctx->Functions.cas_set_ondisk_size_limit(Ctx->c_cas,
431 return Ctx->errorAndDispose(c_err);
436Expected<std::optional<uint64_t>> PluginObjectStore::getStorageSize()
const {
437 if (!Ctx->Functions.cas_get_ondisk_size)
439 char *c_err =
nullptr;
440 int64_t ret = Ctx->Functions.cas_get_ondisk_size(Ctx->c_cas, &c_err);
445 return Ctx->errorAndDispose(c_err);
451Error PluginObjectStore::pruneStorageData() {
452 if (Ctx->Functions.cas_prune_ondisk_data) {
453 char *c_err =
nullptr;
454 if (Ctx->Functions.cas_prune_ondisk_data(Ctx->c_cas, &c_err))
455 return Ctx->errorAndDispose(c_err);
460Error PluginObjectStore::validate(
bool CheckHash)
const {
461 if (Ctx->Functions.cas_validate) {
462 char *c_err =
nullptr;
463 if (Ctx->Functions.cas_validate(Ctx->c_cas, CheckHash, &c_err))
464 return Ctx->errorAndDispose(c_err);
470PluginObjectStore::PluginObjectStore(std::shared_ptr<PluginCASContext> CASCtx)
471 : ObjectStore(*CASCtx), Ctx(std::
move(CASCtx)) {}
481 Expected<std::optional<CASID>> getImpl(ArrayRef<uint8_t> ResolvedKey,
482 bool CanBeDistributed)
const final;
484 Error putImpl(ArrayRef<uint8_t> ResolvedKey,
const CASID &Result,
485 bool CanBeDistributed)
final;
487 PluginActionCache(std::shared_ptr<PluginCASContext>);
492 std::shared_ptr<PluginCASContext> Ctx;
497Expected<std::optional<CASID>>
498PluginActionCache::getImpl(
ArrayRef<uint8_t> ResolvedKey,
499 bool CanBeDistributed)
const {
500 llcas_objectid_t c_value;
501 char *c_err =
nullptr;
503 Ctx->c_cas, llcas_digest_t{ResolvedKey.data(), ResolvedKey.size()},
504 &c_value, CanBeDistributed, &c_err);
507 llcas_digest_t c_digest =
508 Ctx->Functions.objectid_get_digest(Ctx->c_cas, c_value);
514 return Ctx->errorAndDispose(c_err);
519Error PluginActionCache::putImpl(ArrayRef<uint8_t> ResolvedKey,
520 const CASID &Result,
bool CanBeDistributed) {
521 ArrayRef<uint8_t> Hash =
Result.getHash();
522 llcas_objectid_t c_value;
523 char *c_err =
nullptr;
524 if (Ctx->Functions.cas_get_objectid(Ctx->c_cas,
525 llcas_digest_t{Hash.data(), Hash.size()},
527 return Ctx->errorAndDispose(c_err);
529 if (Ctx->Functions.actioncache_put_for_digest(
530 Ctx->c_cas, llcas_digest_t{ResolvedKey.data(), ResolvedKey.size()},
531 c_value, CanBeDistributed, &c_err))
532 return Ctx->errorAndDispose(c_err);
537PluginActionCache::PluginActionCache(std::shared_ptr<PluginCASContext> CASCtx)
538 : ActionCache(*CASCtx), Ctx(std::
move(CASCtx)) {}
540Error PluginActionCache::validate()
const {
541 if (Ctx->Functions.actioncache_validate) {
542 char *c_err =
nullptr;
543 if (Ctx->Functions.actioncache_validate(Ctx->c_cas, &c_err))
544 return Ctx->errorAndDispose(c_err);
554Expected<std::pair<std::shared_ptr<ObjectStore>, std::shared_ptr<ActionCache>>>
557 ArrayRef<std::pair<std::string, std::string>> PluginArgs) {
558 std::shared_ptr<PluginCASContext> Ctx;
559 if (
Error E = PluginCASContext::create(PluginPath, OnDiskPath, PluginArgs)
562 auto CAS = std::make_shared<PluginObjectStore>(Ctx);
563 auto AC = std::make_shared<PluginActionCache>(std::move(Ctx));
564 return std::make_pair(std::move(CAS), std::move(AC));
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file contains the declaration of the ActionCache class, which is the base class for ActionCache ...
static Error reportError(StringRef Message)
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static cl::opt< unsigned > SizeLimit("eif-limit", cl::init(6), cl::Hidden, cl::desc("Size limit in Hexagon early if-conversion"))
This file contains the declaration of the ObjectStore class.
Defines llcas_functions_t, the table of function pointers that is populated by looking up the llcas_*...
struct llcas_cas_options_s * llcas_cas_options_t
#define LLCAS_VERSION_MAJOR
struct llcas_cas_s * llcas_cas_t
#define LLCAS_VERSION_MINOR
llcas_lookup_result_t
Return values for a load operation.
@ LLCAS_LOOKUP_RESULT_NOTFOUND
The object was not found.
@ LLCAS_LOOKUP_RESULT_SUCCESS
The object was found.
@ LLCAS_LOOKUP_RESULT_ERROR
An error occurred.
This file defines the scope_exit class, which executes user-defined cleanup logic at scope exit.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Error takeError()
Take ownership of the stored error.
void reserve(size_type N)
void push_back(const T &Elt)
pointer data()
Return a pointer to the vector's buffer, even if empty().
Represent a constant reference to a string, i.e.
A cache from a key (that describes an action) to the result of performing that action.
Context for CAS identifiers.
Unique identifier for a CAS object.
static CASID create(const CASContext *Context, StringRef Hash)
Create CASID from CASContext and raw hash bytes.
virtual std::unique_ptr< MemoryBuffer > getStandaloneMemoryBufferImpl(ObjectHandle Node, StringRef Name, bool RequiresNullTerminator)
Customization point for getStandaloneMemoryBuffer().
virtual Error exportDataToFile(ObjectHandle Node, StringRef Path) const
Exports the data of an object to a file path.
virtual Expected< ObjectRef > storeFromFile(StringRef Path)
Stores the data of a file into ObjectStore.
This class implements an extremely fast bulk output stream that can only output to a stream.
static LLVM_ABI DynamicLibrary getPermanentLibrary(const char *filename, std::string *errMsg=nullptr)
This function permanently loads the dynamic library at the given path using the library load operatio...
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void validate(const Triple &TT, const FeatureBitset &FeatureBits)
LLVM_ABI Expected< std::pair< std::shared_ptr< ObjectStore >, std::shared_ptr< ActionCache > > > createPluginCASDatabases(StringRef PluginPath, StringRef OnDiskPath, ArrayRef< std::pair< std::string, std::string > > PluginArgs)
Create ObjectStore and ActionCache instances backed by a plugin that implements the C API in "llvm-c/...
initializer< Ty > init(const Ty &Val)
uint64_t getDataSize(const FuncRecordTy *Record)
Return the coverage map data size for the function.
llvm::unique_function< void(llvm::Expected< T >)> Callback
A Callback<T> is a void function that accepts Expected<T>.
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
scope_exit(Callable) -> scope_exit< Callable >
@ Store
The extracted value is stored (ExtractElement only).
LLVM_ABI std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
@ Ref
The access may reference the value stored in memory.
ArrayRef(const T &OneElt) -> ArrayRef< T >
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
StringRef toStringRef(bool B)
Construct a string ref from a boolean.
void(* string_dispose)(char *)
size_t(* object_refs_get_count)(llcas_cas_t, llcas_object_refs_t)
bool(* digest_print)(llcas_cas_t, llcas_digest_t, char **printed_id, char **error)
bool(* cas_options_set_option)(llcas_cas_options_t, const char *name, const char *value, char **error)
llcas_cas_options_t(* cas_options_create)(void)
llcas_object_refs_t(* loaded_object_get_refs)(llcas_cas_t, llcas_loaded_object_t)
void(* cas_options_set_ondisk_path)(llcas_cas_options_t, const char *path)
void(* cas_options_set_client_version)(llcas_cas_options_t, unsigned major, unsigned minor)
llcas_cas_t(* cas_create)(llcas_cas_options_t, char **error)
char *(* cas_get_hash_schema_name)(llcas_cas_t)
void(* cas_options_dispose)(llcas_cas_options_t)
llcas_objectid_t(* object_refs_get_id)(llcas_cas_t, llcas_object_refs_t, size_t index)