2121#include " lldb/Symbol/VariableList.h"
2222#include " lldb/Utility/ArchSpec.h"
2323#include " lldb/Utility/ConstString.h"
24+ #include " lldb/Utility/DataBufferLLVM.h"
2425#include " lldb/Utility/FileSpecList.h"
2526#include " lldb/Utility/LLDBLog.h"
2627#include " lldb/Utility/Log.h"
2728#include " lldb/Utility/UUID.h"
2829#include " lldb/lldb-defines.h"
30+ #include " llvm/ADT/ScopeExit.h"
31+ #include " llvm/Support/FileUtilities.h"
2932
3033#if defined(_WIN32)
3134#include " lldb/Host/windows/PosixApi.h"
3235#endif
3336
3437#include " clang/Driver/Driver.h"
3538#include " llvm/ADT/StringRef.h"
39+ #include " llvm/CAS/CASConfiguration.h"
40+ #include " llvm/CAS/ObjectStore.h"
3641#include " llvm/Support/FileSystem.h"
3742#include " llvm/Support/Threading.h"
3843#include " llvm/Support/raw_ostream.h"
@@ -282,6 +287,32 @@ bool ModuleListProperties::GetSwiftEnableASTContext() const {
282287}
283288// END SWIFT
284289
290+ // START CAS
291+ FileSpec ModuleListProperties::GetCASOnDiskPath () const {
292+ const uint32_t idx = ePropertyCASOnDiskPath;
293+ return GetPropertyAtIndexAs<FileSpec>(idx, {});
294+ }
295+
296+ FileSpec ModuleListProperties::GetCASPluginPath () const {
297+ const uint32_t idx = ePropertyCASPluginPath;
298+ return GetPropertyAtIndexAs<FileSpec>(idx, {});
299+ }
300+
301+ std::vector<std::pair<std::string, std::string>>
302+ ModuleListProperties::GetCASPluginOptions () const {
303+ Args args;
304+ const uint32_t idx = ePropertyCASPluginOptions;
305+ m_collection_sp->GetPropertyAtIndexAsArgs (idx, args);
306+ std::vector<std::pair<std::string, std::string>> options;
307+ for (auto &arg : args) {
308+ llvm::StringRef opt = arg.c_str ();
309+ auto splitted = opt.split (" =" );
310+ options.emplace_back (splitted.first .str (), splitted.second .str ());
311+ }
312+ return options;
313+ }
314+ // END CAS
315+
285316FileSpec ModuleListProperties::GetLLDBIndexCachePath () const {
286317 const uint32_t idx = ePropertyLLDBIndexCachePath;
287318 return GetPropertyAtIndexAs<FileSpec>(idx, {});
@@ -1257,8 +1288,11 @@ class SharedModuleList {
12571288struct SharedModuleListInfo {
12581289 SharedModuleList module_list;
12591290 ModuleListProperties module_list_properties;
1291+ std::shared_ptr<llvm::cas::ObjectStore> cas_object_store;
1292+ std::mutex shared_lock;
12601293};
12611294}
1295+
12621296static SharedModuleListInfo &GetSharedModuleListInfo ()
12631297{
12641298 static SharedModuleListInfo *g_shared_module_list_info = nullptr ;
@@ -1277,6 +1311,47 @@ static SharedModuleList &GetSharedModuleList() {
12771311 return GetSharedModuleListInfo ().module_list ;
12781312}
12791313
1314+ std::optional<llvm::cas::CASConfiguration>
1315+ ModuleList::GetCASConfiguration (FileSpec CandidateConfigSearchPath) {
1316+ // Config CAS from properties.
1317+ llvm::cas::CASConfiguration cas_config;
1318+ cas_config.CASPath =
1319+ ModuleList::GetGlobalModuleListProperties ().GetCASOnDiskPath ().GetPath ();
1320+ cas_config.PluginPath =
1321+ ModuleList::GetGlobalModuleListProperties ().GetCASPluginPath ().GetPath ();
1322+ cas_config.PluginOptions =
1323+ ModuleList::GetGlobalModuleListProperties ().GetCASPluginOptions ();
1324+
1325+ if (!cas_config.CASPath .empty ())
1326+ return cas_config;
1327+
1328+ auto search_config = llvm::cas::CASConfiguration::createFromSearchConfigFile (
1329+ CandidateConfigSearchPath.GetPath ());
1330+ if (search_config)
1331+ return search_config->second ;
1332+
1333+ return std::nullopt ;
1334+ }
1335+
1336+ static llvm::Expected<std::shared_ptr<llvm::cas::ObjectStore>>
1337+ GetOrCreateCASStorage (FileSpec CandidateConfigSearchPath) {
1338+ auto &shared_module_list = GetSharedModuleListInfo ();
1339+ if (shared_module_list.cas_object_store )
1340+ return shared_module_list.cas_object_store ;
1341+
1342+ auto config = ModuleList::GetCASConfiguration (CandidateConfigSearchPath);
1343+ if (!config)
1344+ return nullptr ;
1345+
1346+ auto cas = config->createDatabases ();
1347+ if (!cas)
1348+ return cas.takeError ();
1349+
1350+ std::scoped_lock<std::mutex> lock (shared_module_list.shared_lock );
1351+ shared_module_list.cas_object_store = std::move (cas->first );
1352+ return shared_module_list.cas_object_store ;
1353+ }
1354+
12801355ModuleListProperties &ModuleList::GetGlobalModuleListProperties () {
12811356 return GetSharedModuleListInfo ().module_list_properties ;
12821357}
@@ -1548,6 +1623,65 @@ ModuleList::GetSharedModule(const ModuleSpec &module_spec, ModuleSP &module_sp,
15481623 return error;
15491624}
15501625
1626+ static llvm::Expected<bool > loadModuleFromCAS (ConstString module_name,
1627+ llvm::StringRef cas_id,
1628+ FileSpec cu_path,
1629+ ModuleSpec &module_spec) {
1630+ auto maybe_cas = GetOrCreateCASStorage (cu_path);
1631+ if (!maybe_cas)
1632+ return maybe_cas.takeError ();
1633+
1634+ auto cas = std::move (*maybe_cas);
1635+ if (!cas) {
1636+ LLDB_LOG (GetLog (LLDBLog::Modules),
1637+ " skip loading module '{0}' from CAS: CAS is not available" ,
1638+ module_name);
1639+ return false ;
1640+ }
1641+
1642+ auto id = cas->parseID (cas_id);
1643+ if (!id) {
1644+ LLDB_LOG (GetLog (LLDBLog::Modules), " '{0}' is not valid CASID: {1}" , cas_id,
1645+ toString (id.takeError ()));
1646+ return false ;
1647+ }
1648+
1649+ auto module_proxy = cas->getProxy (*id);
1650+ if (!module_proxy)
1651+ return module_proxy.takeError ();
1652+
1653+ auto file_buffer =
1654+ std::make_shared<DataBufferLLVM>(module_proxy->getMemoryBuffer ());
1655+
1656+ // Swap out the module_spec with the one loaded via CAS.
1657+ ModuleSpec loaded (module_spec.GetFileSpec (), module_spec.GetUUID (),
1658+ std::move (file_buffer));
1659+ loaded.GetArchitecture () = module_spec.GetArchitecture ();
1660+ module_spec = loaded;
1661+
1662+ LLDB_LOG (GetLog (LLDBLog::Modules), " loading module '{0}' using CASID '{1}'" ,
1663+ module_name, cas_id);
1664+ return true ;
1665+ }
1666+
1667+ llvm::Expected<bool > ModuleList::GetSharedModuleFromCAS (
1668+ ConstString module_name, llvm::StringRef cas_id, FileSpec cu_path,
1669+ ModuleSpec &module_spec, lldb::ModuleSP &module_sp) {
1670+ auto loaded = loadModuleFromCAS (module_name, cas_id, cu_path, module_spec);
1671+ if (!loaded)
1672+ return loaded.takeError ();
1673+
1674+ if (!*loaded)
1675+ return false ;
1676+
1677+ auto status =
1678+ GetSharedModule (module_spec, module_sp, nullptr , nullptr , nullptr ,
1679+ /* always_create=*/ true );
1680+ if (status.Success ())
1681+ return true ;
1682+ return status.takeError ();
1683+ }
1684+
15511685bool ModuleList::RemoveSharedModule (lldb::ModuleSP &module_sp) {
15521686 return GetSharedModuleList ().Remove (module_sp);
15531687}
0 commit comments