33 void printIDImpl(raw_ostream &OS,
const CASID &ID)
const final;
35 StringRef getHashSchemaIdentifier()
const final {
return SchemaName; }
37 static Expected<std::shared_ptr<PluginCASContext>>
38 create(StringRef PluginPath, StringRef OnDiskPath,
39 ArrayRef<std::pair<std::string, std::string>> PluginArgs);
41 ~PluginCASContext() { Functions.cas_dispose(c_cas); }
43 llcas_functions_t Functions{};
45 std::string SchemaName;
47 static Error errorAndDispose(
char *c_err,
const llcas_functions_t &Funcs) {
53 Error errorAndDispose(
char *c_err)
const {
54 return errorAndDispose(c_err, Functions);
61 ArrayRef<uint8_t> Hash =
ID.getHash();
62 char *c_printed_id =
nullptr;
63 char *c_err =
nullptr;
64 if (Functions.
digest_print(c_cas, llcas_digest_t{Hash.data(), Hash.size()},
65 &c_printed_id, &c_err))
71Expected<std::shared_ptr<PluginCASContext>> PluginCASContext::create(
72 StringRef PluginPath, StringRef OnDiskPath,
73 ArrayRef<std::pair<std::string, std::string>> PluginArgs) {
80 SmallString<256> PathBuf = PluginPath;
82 sys::DynamicLibrary
Lib =
87 llcas_functions_t Functions{};
89#define CASPLUGINAPI_FUNCTION(name, required) \
90 if (!(Functions.name = (decltype(llcas_functions_t::name)) \
91 Lib.getAddressOfSymbol("llcas_" #name))) { \
93 return reportError("failed symbol 'llcas_" #name "' lookup"); \
95#include "PluginAPI_functions.def"
96#undef CASPLUGINAPI_FUNCTION
103 SmallString<256> OnDiskPathBuf = OnDiskPath;
105 for (
const auto &Pair : PluginArgs) {
106 char *c_err =
nullptr;
108 Pair.second.c_str(), &c_err))
109 return errorAndDispose(c_err, Functions);
112 char *c_err =
nullptr;
115 return errorAndDispose(c_err, Functions);
118 std::string SchemaName = c_schema;
121 auto Ctx = std::make_shared<PluginCASContext>();
122 Ctx->Functions = Functions;
124 Ctx->SchemaName = std::move(SchemaName);
134class PluginObjectStore :
public ObjectStore {
136 Expected<CASID> parseID(StringRef ID)
final;
138 ArrayRef<char>
Data)
final;
139 Expected<ObjectRef> storeFromFile(StringRef Path)
final;
140 Error exportDataToFile(ObjectHandle Node, StringRef Path)
const final;
141 CASID getID(ObjectRef
Ref)
const final;
142 std::optional<ObjectRef> getReference(
const CASID &ID)
const final;
143 Expected<bool> isMaterialized(ObjectRef
Ref)
const final;
144 Expected<std::optional<ObjectHandle>> loadIfExists(ObjectRef
Ref)
final;
145 uint64_t
getDataSize(ObjectHandle Node)
const final;
146 Error forEachRef(ObjectHandle Node,
147 function_ref<
Error(ObjectRef)> Callback)
const final;
148 ObjectRef readRef(ObjectHandle Node,
size_t I)
const final;
149 size_t getNumRefs(ObjectHandle Node)
const final;
150 ArrayRef<char> getData(ObjectHandle Node,
151 bool RequiresNullTerminator =
false)
const final;
160 Expected<std::optional<uint64_t>> getStorageSize()
const final;
161 Error pruneStorageData() final;
163 PluginObjectStore(std::shared_ptr<PluginCASContext>);
166 ObjectRef makeRef(uint64_t InternalRef)
const {
167 return makeObjectRef(InternalRef);
170 std::shared_ptr<PluginCASContext> Ctx;
175Expected<CASID> PluginObjectStore::parseID(StringRef ID) {
177 SmallString<148> IDBuf(ID);
180 auto parseDigest = [&]() -> Expected<unsigned> {
181 char *c_err =
nullptr;
182 unsigned NumBytes = Ctx->Functions.digest_parse(
183 Ctx->c_cas, IDBuf.c_str(), BytesBuf.data(), BytesBuf.size(), &c_err);
185 return Ctx->errorAndDispose(c_err);
189 Expected<unsigned> NumBytes = parseDigest();
193 if (*NumBytes > BytesBuf.size()) {
194 BytesBuf.resize(*NumBytes);
195 NumBytes = parseDigest();
198 assert(*NumBytes == BytesBuf.size());
200 BytesBuf.truncate(*NumBytes);
207 ArrayRef<char>
Data) {
210 for (ObjectRef
Ref : Refs) {
211 c_ids.
push_back(llcas_objectid_t{
Ref.getInternalRef(*
this)});
214 llcas_objectid_t c_stored_id;
215 char *c_err =
nullptr;
216 if (Ctx->Functions.cas_store_object(
217 Ctx->c_cas, llcas_data_t{Data.data(), Data.size()}, c_ids.
data(),
218 c_ids.
size(), &c_stored_id, &c_err))
219 return Ctx->errorAndDispose(c_err);
221 return makeObjectRef(c_stored_id.
opaque);
224Expected<ObjectRef> PluginObjectStore::storeFromFile(StringRef Path) {
225 if (!Ctx->Functions.cas_store_from_filepath)
228 llcas_objectid_t c_stored_id;
229 char *c_err =
nullptr;
230 std::string PathStr =
Path.str();
231 if (Ctx->Functions.cas_store_from_filepath(Ctx->c_cas, PathStr.c_str(),
232 &c_stored_id, &c_err))
233 return Ctx->errorAndDispose(c_err);
235 return makeObjectRef(c_stored_id.
opaque);
238Error PluginObjectStore::exportDataToFile(ObjectHandle Node,
239 StringRef Path)
const {
240 if (!Ctx->Functions.loaded_object_export_data_to_filepath)
243 char *c_err =
nullptr;
244 std::string PathStr =
Path.str();
245 if (Ctx->Functions.loaded_object_export_data_to_filepath(
246 Ctx->c_cas, llcas_loaded_object_t{Node.getInternalRef(*this)},
247 PathStr.c_str(), &c_err))
248 return Ctx->errorAndDispose(c_err);
257CASID PluginObjectStore::getID(ObjectRef
Ref)
const {
258 llcas_objectid_t c_id{
Ref.getInternalRef(*
this)};
259 llcas_digest_t c_digest =
260 Ctx->Functions.objectid_get_digest(Ctx->c_cas, c_id);
264std::optional<ObjectRef>
265PluginObjectStore::getReference(
const CASID &ID)
const {
266 ArrayRef<uint8_t> Hash =
ID.getHash();
267 llcas_objectid_t c_id;
268 char *c_err =
nullptr;
269 if (Ctx->Functions.cas_get_objectid(
270 Ctx->c_cas, llcas_digest_t{Hash.data(), Hash.size()}, &c_id, &c_err))
273 return makeObjectRef(c_id.
opaque);
276Expected<bool> PluginObjectStore::isMaterialized(ObjectRef
Ref)
const {
277 llcas_objectid_t c_id{
Ref.getInternalRef(*
this)};
278 char *c_err =
nullptr;
280 Ctx->c_cas, c_id,
false, &c_err);
287 return Ctx->errorAndDispose(c_err);
292Expected<std::optional<ObjectHandle>>
293PluginObjectStore::loadIfExists(ObjectRef
Ref) {
294 llcas_objectid_t c_id{
Ref.getInternalRef(*
this)};
295 llcas_loaded_object_t c_obj;
296 char *c_err =
nullptr;
298 Ctx->Functions.cas_load_object(Ctx->c_cas, c_id, &c_obj, &c_err);
301 return makeObjectHandle(c_obj.
opaque);
305 return Ctx->errorAndDispose(c_err);
312class ObjectRefsWrapper {
314 ObjectRefsWrapper(
const ObjectHandle &Node,
const PluginObjectStore &
Store)
316 llcas_loaded_object_t c_obj{
Node.getInternalRef(
Store)};
320 size_t size()
const {
324 ObjectRef operator[](
size_t I)
const {
325 llcas_objectid_t c_id =
331 const PluginObjectStore &
Store;
332 PluginCASContext &Ctx;
333 llcas_object_refs_t c_refs;
339Error PluginObjectStore::forEachRef(
340 ObjectHandle Node, function_ref<
Error(ObjectRef)> Callback)
const {
341 ObjectRefsWrapper Refs(Node, *
this);
342 for (
unsigned I = 0,
E = Refs.size();
I !=
E; ++
I) {
349ObjectRef PluginObjectStore::readRef(ObjectHandle Node,
size_t I)
const {
350 ObjectRefsWrapper Refs(Node, *
this);
354size_t PluginObjectStore::getNumRefs(ObjectHandle Node)
const {
355 ObjectRefsWrapper Refs(Node, *
this);
361uint64_t PluginObjectStore::getDataSize(ObjectHandle Node)
const {
362 ArrayRef<char>
Data = getData(Node);
366ArrayRef<char> PluginObjectStore::getData(ObjectHandle Node,
367 bool RequiresNullTerminator)
const {
370 llcas_data_t c_data = Ctx->Functions.loaded_object_get_data(
371 Ctx->c_cas, llcas_loaded_object_t{Node.getInternalRef(*this)});
375Error PluginObjectStore::setSizeLimit(std::optional<uint64_t>
SizeLimit) {
376 if (Ctx->Functions.cas_set_ondisk_size_limit) {
377 char *c_err =
nullptr;
378 if (Ctx->Functions.cas_set_ondisk_size_limit(Ctx->c_cas,
380 return Ctx->errorAndDispose(c_err);
385Expected<std::optional<uint64_t>> PluginObjectStore::getStorageSize()
const {
386 if (!Ctx->Functions.cas_get_ondisk_size)
388 char *c_err =
nullptr;
389 int64_t ret = Ctx->Functions.cas_get_ondisk_size(Ctx->c_cas, &c_err);
394 return Ctx->errorAndDispose(c_err);
400Error PluginObjectStore::pruneStorageData() {
401 if (Ctx->Functions.cas_prune_ondisk_data) {
402 char *c_err =
nullptr;
403 if (Ctx->Functions.cas_prune_ondisk_data(Ctx->c_cas, &c_err))
404 return Ctx->errorAndDispose(c_err);
409Error PluginObjectStore::validate(
bool CheckHash)
const {
410 if (Ctx->Functions.cas_validate) {
411 char *c_err =
nullptr;
412 if (Ctx->Functions.cas_validate(Ctx->c_cas, CheckHash, &c_err))
413 return Ctx->errorAndDispose(c_err);
419PluginObjectStore::PluginObjectStore(std::shared_ptr<PluginCASContext> CASCtx)
420 : ObjectStore(*CASCtx), Ctx(std::
move(CASCtx)) {}
430 Expected<std::optional<CASID>> getImpl(ArrayRef<uint8_t> ResolvedKey,
431 bool CanBeDistributed)
const final;
433 Error putImpl(ArrayRef<uint8_t> ResolvedKey,
const CASID &Result,
434 bool CanBeDistributed)
final;
436 PluginActionCache(std::shared_ptr<PluginCASContext>);
441 std::shared_ptr<PluginCASContext> Ctx;
446Expected<std::optional<CASID>>
447PluginActionCache::getImpl(
ArrayRef<uint8_t> ResolvedKey,
448 bool CanBeDistributed)
const {
449 llcas_objectid_t c_value;
450 char *c_err =
nullptr;
452 Ctx->c_cas, llcas_digest_t{ResolvedKey.data(), ResolvedKey.size()},
453 &c_value, CanBeDistributed, &c_err);
456 llcas_digest_t c_digest =
457 Ctx->Functions.objectid_get_digest(Ctx->c_cas, c_value);
463 return Ctx->errorAndDispose(c_err);
468Error PluginActionCache::putImpl(ArrayRef<uint8_t> ResolvedKey,
469 const CASID &Result,
bool CanBeDistributed) {
470 ArrayRef<uint8_t> Hash =
Result.getHash();
471 llcas_objectid_t c_value;
472 char *c_err =
nullptr;
473 if (Ctx->Functions.cas_get_objectid(Ctx->c_cas,
474 llcas_digest_t{Hash.data(), Hash.size()},
476 return Ctx->errorAndDispose(c_err);
478 if (Ctx->Functions.actioncache_put_for_digest(
479 Ctx->c_cas, llcas_digest_t{ResolvedKey.data(), ResolvedKey.size()},
480 c_value, CanBeDistributed, &c_err))
481 return Ctx->errorAndDispose(c_err);
486PluginActionCache::PluginActionCache(std::shared_ptr<PluginCASContext> CASCtx)
487 : ActionCache(*CASCtx), Ctx(std::
move(CASCtx)) {}
489Error PluginActionCache::validate()
const {
490 if (Ctx->Functions.actioncache_validate) {
491 char *c_err =
nullptr;
492 if (Ctx->Functions.actioncache_validate(Ctx->c_cas, &c_err))
493 return Ctx->errorAndDispose(c_err);
503Expected<std::pair<std::shared_ptr<ObjectStore>, std::shared_ptr<ActionCache>>>
506 ArrayRef<std::pair<std::string, std::string>> PluginArgs) {
507 std::shared_ptr<PluginCASContext> Ctx;
508 if (
Error E = PluginCASContext::create(PluginPath, OnDiskPath, PluginArgs)
511 auto CAS = std::make_shared<PluginObjectStore>(Ctx);
512 auto AC = std::make_shared<PluginActionCache>(std::move(Ctx));
513 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 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/...
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)