2626#include " lldb/Utility/Log.h"
2727#include " lldb/Utility/UUID.h"
2828#include " lldb/lldb-defines.h"
29+ #include " llvm/ADT/ScopeExit.h"
30+ #include " llvm/Support/FileUtilities.h"
2931
3032#if defined(_WIN32)
3133#include " lldb/Host/windows/PosixApi.h"
3234#endif
3335
3436#include " clang/Driver/Driver.h"
3537#include " llvm/ADT/StringRef.h"
38+ #include " llvm/CAS/CASConfiguration.h"
39+ #include " llvm/CAS/ObjectStore.h"
3640#include " llvm/Support/FileSystem.h"
3741#include " llvm/Support/Threading.h"
3842#include " llvm/Support/raw_ostream.h"
@@ -282,6 +286,32 @@ bool ModuleListProperties::GetSwiftEnableASTContext() const {
282286}
283287// END SWIFT
284288
289+ // START CAS
290+ FileSpec ModuleListProperties::GetCASOnDiskPath () const {
291+ const uint32_t idx = ePropertyCASOnDiskPath;
292+ return GetPropertyAtIndexAs<FileSpec>(idx, {});
293+ }
294+
295+ FileSpec ModuleListProperties::GetCASPluginPath () const {
296+ const uint32_t idx = ePropertyCASPluginPath;
297+ return GetPropertyAtIndexAs<FileSpec>(idx, {});
298+ }
299+
300+ std::vector<std::pair<std::string, std::string>>
301+ ModuleListProperties::GetCASPluginOptions () const {
302+ Args args;
303+ const uint32_t idx = ePropertyCASPluginOptions;
304+ m_collection_sp->GetPropertyAtIndexAsArgs (idx, args);
305+ std::vector<std::pair<std::string, std::string>> options;
306+ for (auto &arg : args) {
307+ llvm::StringRef opt = arg.c_str ();
308+ auto splitted = opt.split (" =" );
309+ options.emplace_back (splitted.first .str (), splitted.second .str ());
310+ }
311+ return options;
312+ }
313+ // END CAS
314+
285315FileSpec ModuleListProperties::GetLLDBIndexCachePath () const {
286316 const uint32_t idx = ePropertyLLDBIndexCachePath;
287317 return GetPropertyAtIndexAs<FileSpec>(idx, {});
@@ -1257,8 +1287,11 @@ class SharedModuleList {
12571287struct SharedModuleListInfo {
12581288 SharedModuleList module_list;
12591289 ModuleListProperties module_list_properties;
1290+ std::shared_ptr<llvm::cas::ObjectStore> cas_object_store;
1291+ std::mutex shared_lock;
12601292};
12611293}
1294+
12621295static SharedModuleListInfo &GetSharedModuleListInfo ()
12631296{
12641297 static SharedModuleListInfo *g_shared_module_list_info = nullptr ;
@@ -1277,6 +1310,45 @@ static SharedModuleList &GetSharedModuleList() {
12771310 return GetSharedModuleListInfo ().module_list ;
12781311}
12791312
1313+ static std::shared_ptr<llvm::cas::ObjectStore>
1314+ GetOrCreateCASStorage (FileSpec CandidateConfigSearchPath) {
1315+ auto &shared_module_list = GetSharedModuleListInfo ();
1316+ if (shared_module_list.cas_object_store )
1317+ return shared_module_list.cas_object_store ;
1318+
1319+ std::scoped_lock<std::mutex> lock (shared_module_list.shared_lock );
1320+ // Config CAS from properties.
1321+ llvm::cas::CASConfiguration cas_config;
1322+ cas_config.CASPath =
1323+ ModuleList::GetGlobalModuleListProperties ().GetCASOnDiskPath ().GetPath ();
1324+ cas_config.PluginPath =
1325+ ModuleList::GetGlobalModuleListProperties ().GetCASPluginPath ().GetPath ();
1326+ cas_config.PluginOptions =
1327+ ModuleList::GetGlobalModuleListProperties ().GetCASPluginOptions ();
1328+
1329+ if (!cas_config.CASPath .empty ()) {
1330+ if (auto maybe_cas = cas_config.createDatabases ()) {
1331+ shared_module_list.cas_object_store = std::move (maybe_cas->first );
1332+ return shared_module_list.cas_object_store ;
1333+ } else
1334+ llvm::consumeError (maybe_cas.takeError ());
1335+ }
1336+
1337+ // Try search from candidiate path.
1338+ auto search_config = llvm::cas::CASConfiguration::createFromSearchConfigFile (
1339+ CandidateConfigSearchPath.GetPath ());
1340+ if (!search_config)
1341+ return nullptr ;
1342+
1343+ if (auto maybe_cas = search_config->second .createDatabases ()) {
1344+ shared_module_list.cas_object_store = std::move (maybe_cas->first );
1345+ return shared_module_list.cas_object_store ;
1346+ } else
1347+ llvm::consumeError (maybe_cas.takeError ());
1348+
1349+ return nullptr ;
1350+ }
1351+
12801352ModuleListProperties &ModuleList::GetGlobalModuleListProperties () {
12811353 return GetSharedModuleListInfo ().module_list_properties ;
12821354}
@@ -1548,6 +1620,59 @@ ModuleList::GetSharedModule(const ModuleSpec &module_spec, ModuleSP &module_sp,
15481620 return error;
15491621}
15501622
1623+ static llvm::Error loadModuleFromCAS (ConstString module_name,
1624+ const char *cas_id, FileSpec cu_path,
1625+ ModuleSpec &module_spec) {
1626+ auto cas = GetOrCreateCASStorage (cu_path);
1627+ if (!cas)
1628+ return llvm::createStringError (" CAS is not available" );
1629+ auto id = cas->parseID (cas_id);
1630+ if (!id)
1631+ return id.takeError ();
1632+
1633+ auto module_proxy = cas->getProxy (*id);
1634+ if (!module_proxy)
1635+ return module_proxy.takeError ();
1636+
1637+ // Create a temporary file that holds the module info.
1638+ llvm::SmallString<0 > name;
1639+ int fd;
1640+ auto ec =
1641+ llvm::sys::fs::createTemporaryFile (" lldb-module-cas" , " pcm" , fd, name);
1642+ if (ec || fd <= 0 )
1643+ return llvm::createStringError (
1644+ " could not create temporary file for module" );
1645+
1646+ NativeFile file (fd, File::eOpenOptionWriteOnly, true );
1647+ size_t num_bytes = module_proxy->getData ().size ();
1648+ file.Write (module_proxy->getData ().data (), num_bytes);
1649+
1650+ Log *log = GetLog (LLDBLog::Modules);
1651+ if (log != nullptr )
1652+ LLDB_LOGF (log, " loading module '%s' using CASID '%s' from temp file: %s" ,
1653+ module_name.AsCString (), cas_id, name.c_str ());
1654+
1655+ module_spec.GetFileSpec ().SetFile (name, FileSpec::Style::native);
1656+ return llvm::Error::success ();
1657+ }
1658+
1659+ Status ModuleList::GetSharedModuleFromCAS (ConstString module_name,
1660+ const char *cas_id, FileSpec cu_path,
1661+ ModuleSpec &module_spec,
1662+ lldb::ModuleSP &module_sp) {
1663+ auto err = loadModuleFromCAS (module_name, cas_id, cu_path, module_spec);
1664+ if (err)
1665+ return Status::FromErrorString (llvm::toString (std::move (err)).c_str ());
1666+
1667+ // Remove the temporary file created from CAS content after module is loaded.
1668+ auto cleanup_module = llvm::make_scope_exit ([&]() {
1669+ llvm::sys::fs::remove (
1670+ module_spec.GetFileSpec ().GetPathAsConstString ().GetStringRef ());
1671+ });
1672+
1673+ return GetSharedModule (module_spec, module_sp, nullptr , nullptr , nullptr );
1674+ }
1675+
15511676bool ModuleList::RemoveSharedModule (lldb::ModuleSP &module_sp) {
15521677 return GetSharedModuleList ().Remove (module_sp);
15531678}
0 commit comments