1717#include " lldb/Interpreter/Property.h"
1818#include " lldb/Symbol/ObjectFile.h"
1919#include " lldb/Symbol/SymbolContext.h"
20+ #include " lldb/Symbol/SymbolFile.h"
2021#include " lldb/Symbol/TypeList.h"
2122#include " lldb/Symbol/VariableList.h"
2223#include " lldb/Utility/ArchSpec.h"
2829#include " lldb/Utility/UUID.h"
2930#include " lldb/lldb-defines.h"
3031#include " llvm/ADT/ScopeExit.h"
32+ #include " llvm/Support/Error.h"
3133#include " llvm/Support/FileUtilities.h"
3234
3335#if defined(_WIN32)
@@ -304,6 +306,11 @@ FileSpec ModuleListProperties::GetCASOnDiskPath() const {
304306 return GetPropertyAtIndexAs<FileSpec>(idx, {});
305307}
306308
309+ bool ModuleListProperties::SetCASOnDiskPath (const FileSpec &path) {
310+ const uint32_t idx = ePropertyCASOnDiskPath;
311+ return SetPropertyAtIndex (idx, path);
312+ }
313+
307314FileSpec ModuleListProperties::GetCASPluginPath () const {
308315 const uint32_t idx = ePropertyCASPluginPath;
309316 return GetPropertyAtIndexAs<FileSpec>(idx, {});
@@ -1299,7 +1306,8 @@ class SharedModuleList {
12991306struct SharedModuleListInfo {
13001307 SharedModuleList module_list;
13011308 ModuleListProperties module_list_properties;
1302- std::shared_ptr<llvm::cas::ObjectStore> cas_object_store;
1309+ // TODO: This should be an LRU cache of multiple CAS.
1310+ ModuleList::CAS cas = {};
13031311 std::mutex shared_lock;
13041312};
13051313}
@@ -1322,8 +1330,8 @@ static SharedModuleList &GetSharedModuleList() {
13221330 return GetSharedModuleListInfo ().module_list ;
13231331}
13241332
1325- std::optional<llvm::cas::CASConfiguration>
1326- ModuleList:: GetCASConfiguration (FileSpec CandidateConfigSearchPath) {
1333+ static std::optional<llvm::cas::CASConfiguration>
1334+ GetCASConfiguration (FileSpec CandidateConfigSearchPath) {
13271335 // Config CAS from properties.
13281336 llvm::cas::CASConfiguration cas_config;
13291337 cas_config.CASPath =
@@ -1344,25 +1352,6 @@ ModuleList::GetCASConfiguration(FileSpec CandidateConfigSearchPath) {
13441352 return std::nullopt ;
13451353}
13461354
1347- static llvm::Expected<std::shared_ptr<llvm::cas::ObjectStore>>
1348- GetOrCreateCASStorage (FileSpec CandidateConfigSearchPath) {
1349- auto &shared_module_list = GetSharedModuleListInfo ();
1350- if (shared_module_list.cas_object_store )
1351- return shared_module_list.cas_object_store ;
1352-
1353- auto config = ModuleList::GetCASConfiguration (CandidateConfigSearchPath);
1354- if (!config)
1355- return nullptr ;
1356-
1357- auto cas = config->createDatabases ();
1358- if (!cas)
1359- return cas.takeError ();
1360-
1361- std::scoped_lock<std::mutex> lock (shared_module_list.shared_lock );
1362- shared_module_list.cas_object_store = std::move (cas->first );
1363- return shared_module_list.cas_object_store ;
1364- }
1365-
13661355ModuleListProperties &ModuleList::GetGlobalModuleListProperties () {
13671356 return GetSharedModuleListInfo ().module_list_properties ;
13681357}
@@ -1634,19 +1623,18 @@ ModuleList::GetSharedModule(const ModuleSpec &module_spec, ModuleSP &module_sp,
16341623 return error;
16351624}
16361625
1637- static llvm::Expected<bool > loadModuleFromCAS (ConstString module_name,
1638- llvm::StringRef cas_id,
1639- FileSpec cu_path,
1640- ModuleSpec &module_spec) {
1641- auto maybe_cas = GetOrCreateCASStorage (cu_path);
1626+ static llvm::Expected<bool > loadModuleFromCASImpl (llvm::StringRef cas_id,
1627+ const lldb::ModuleSP &nearby,
1628+ ModuleSpec &module_spec) {
1629+ auto maybe_cas = ModuleList::GetOrCreateCAS (nearby);
16421630 if (!maybe_cas)
16431631 return maybe_cas.takeError ();
16441632
1645- auto cas = std::move (* maybe_cas);
1633+ auto cas = std::move (maybe_cas-> object_store );
16461634 if (!cas) {
16471635 LLDB_LOG (GetLog (LLDBLog::Modules),
16481636 " skip loading module '{0}' from CAS: CAS is not available" ,
1649- module_name );
1637+ cas_id );
16501638 return false ;
16511639 }
16521640
@@ -1670,15 +1658,96 @@ static llvm::Expected<bool> loadModuleFromCAS(ConstString module_name,
16701658 loaded.GetArchitecture () = module_spec.GetArchitecture ();
16711659 module_spec = loaded;
16721660
1673- LLDB_LOG (GetLog (LLDBLog::Modules), " loading module '{0}' using CASID '{1 }'" ,
1674- module_name, cas_id);
1661+ LLDB_LOG (GetLog (LLDBLog::Modules), " loading module using CASID '{0 }'" ,
1662+ cas_id);
16751663 return true ;
16761664}
16771665
1666+ // / Load the module referenced by \c cas_id from a CAS located
1667+ // / near \c nearby.
1668+ static llvm::Expected<bool > loadModuleFromCAS (llvm::StringRef cas_id,
1669+ const lldb::ModuleSP &nearby,
1670+ ModuleSpec &module_spec) {
1671+ static llvm::StringMap<bool > g_cache;
1672+ static std::recursive_mutex g_cache_lock;
1673+ std::scoped_lock<std::recursive_mutex> lock (g_cache_lock);
1674+ auto cached = g_cache.find (cas_id);
1675+ if (cached != g_cache.end ())
1676+ return cached->second ;
1677+ auto result = loadModuleFromCASImpl (cas_id, nearby, module_spec);
1678+ // Errors are only returned the first time.
1679+ g_cache.insert ({cas_id, result ? *result : false });
1680+ return result;
1681+ }
1682+
1683+ llvm::Expected<ModuleList::CAS>
1684+ ModuleList::GetOrCreateCAS (const ModuleSP &module_sp) {
1685+ if (!module_sp)
1686+ return llvm::createStringError (" no lldb::Module available" );
1687+
1688+ auto &shared_module_list = GetSharedModuleListInfo ();
1689+ std::scoped_lock<std::mutex> lock (shared_module_list.shared_lock );
1690+ if (shared_module_list.cas .object_store )
1691+ return shared_module_list.cas ;
1692+
1693+ std::set<FileSpec> unique_paths;
1694+ auto insert_module_path = [&](const ModuleSP &m) -> IterationAction {
1695+ if (m) {
1696+ FileSpec path = m->GetFileSpec ();
1697+ path.ClearFilename ();
1698+ unique_paths.insert (path);
1699+ }
1700+ return IterationAction::Continue;
1701+ };
1702+ insert_module_path (module_sp);
1703+
1704+ std::optional<llvm::cas::CASConfiguration> cas_config;
1705+ for (auto &path : unique_paths)
1706+ cas_config = GetCASConfiguration (path);
1707+ if (!cas_config) {
1708+ unique_paths.clear ();
1709+ insert_module_path (module_sp);
1710+ if (SymbolFile *sf = module_sp->GetSymbolFile ()) {
1711+ sf->GetDebugInfoModules ().ForEach (insert_module_path);
1712+ for (auto &path : unique_paths)
1713+ if ((cas_config = GetCASConfiguration (path)))
1714+ break ;
1715+ }
1716+ }
1717+ if (!cas_config &&
1718+ !ModuleList::GetGlobalModuleListProperties ().GetCASOnDiskPath ())
1719+ for (auto &path : unique_paths) {
1720+ llvm::StringRef parent = path.GetDirectory ().GetStringRef ();
1721+ while (!parent.empty () &&
1722+ llvm::sys::path::filename (parent) != " DerivedData" )
1723+ parent = llvm::sys::path::parent_path (parent);
1724+ if (parent.empty ())
1725+ continue ;
1726+ llvm::SmallString<256 > cas_path (parent);
1727+ llvm::sys::path::append (cas_path, " CompilationCache.noindex" , " builtin" );
1728+ FileSpec fs = FileSpec (cas_path);
1729+ ModuleList::GetGlobalModuleListProperties ().SetCASOnDiskPath (fs);
1730+ cas_config = GetCASConfiguration (fs);
1731+ if (cas_config)
1732+ break ;
1733+ }
1734+
1735+ if (!cas_config)
1736+ return llvm::createStringError (" no CAS available" );
1737+ auto cas = cas_config->createDatabases ();
1738+ if (!cas)
1739+ return cas.takeError ();
1740+
1741+ shared_module_list.cas = {
1742+ std::make_shared<llvm::cas::CASConfiguration>(*cas_config),
1743+ std::move (cas->first ), std::move (cas->second )};
1744+ return shared_module_list.cas ;
1745+ }
1746+
16781747llvm::Expected<bool > ModuleList::GetSharedModuleFromCAS (
1679- ConstString module_name, llvm::StringRef cas_id, FileSpec cu_path ,
1748+ llvm::StringRef cas_id, const lldb::ModuleSP &nearby ,
16801749 ModuleSpec &module_spec, lldb::ModuleSP &module_sp) {
1681- auto loaded = loadModuleFromCAS (module_name, cas_id, cu_path , module_spec);
1750+ auto loaded = loadModuleFromCAS (cas_id, nearby , module_spec);
16821751 if (!loaded)
16831752 return loaded.takeError ();
16841753
0 commit comments