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, {});
@@ -1253,8 +1283,11 @@ class SharedModuleList {
12531283struct SharedModuleListInfo {
12541284 SharedModuleList module_list;
12551285 ModuleListProperties module_list_properties;
1286+ std::shared_ptr<llvm::cas::ObjectStore> cas_object_store;
1287+ std::mutex shared_lock;
12561288};
12571289}
1290+
12581291static SharedModuleListInfo &GetSharedModuleListInfo ()
12591292{
12601293 static SharedModuleListInfo *g_shared_module_list_info = nullptr ;
@@ -1273,6 +1306,45 @@ static SharedModuleList &GetSharedModuleList() {
12731306 return GetSharedModuleListInfo ().module_list ;
12741307}
12751308
1309+ static std::shared_ptr<llvm::cas::ObjectStore>
1310+ GetOrCreateCASStorage (FileSpec CandidateConfigSearchPath) {
1311+ auto &shared_module_list = GetSharedModuleListInfo ();
1312+ if (shared_module_list.cas_object_store )
1313+ return shared_module_list.cas_object_store ;
1314+
1315+ std::scoped_lock<std::mutex> lock (shared_module_list.shared_lock );
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+ if (auto maybe_cas = cas_config.createDatabases ()) {
1327+ shared_module_list.cas_object_store = std::move (maybe_cas->first );
1328+ return shared_module_list.cas_object_store ;
1329+ } else
1330+ llvm::consumeError (maybe_cas.takeError ());
1331+ }
1332+
1333+ // Try search from candidiate path.
1334+ auto search_config = llvm::cas::CASConfiguration::createFromSearchConfigFile (
1335+ CandidateConfigSearchPath.GetPath ());
1336+ if (!search_config)
1337+ return nullptr ;
1338+
1339+ if (auto maybe_cas = search_config->second .createDatabases ()) {
1340+ shared_module_list.cas_object_store = std::move (maybe_cas->first );
1341+ return shared_module_list.cas_object_store ;
1342+ } else
1343+ llvm::consumeError (maybe_cas.takeError ());
1344+
1345+ return nullptr ;
1346+ }
1347+
12761348ModuleListProperties &ModuleList::GetGlobalModuleListProperties () {
12771349 return GetSharedModuleListInfo ().module_list_properties ;
12781350}
@@ -1544,6 +1616,59 @@ ModuleList::GetSharedModule(const ModuleSpec &module_spec, ModuleSP &module_sp,
15441616 return error;
15451617}
15461618
1619+ static llvm::Error loadModuleFromCAS (ConstString module_name,
1620+ const char *cas_id, FileSpec cu_path,
1621+ ModuleSpec &module_spec) {
1622+ auto cas = GetOrCreateCASStorage (cu_path);
1623+ if (!cas)
1624+ return llvm::createStringError (" CAS is not available" );
1625+ auto id = cas->parseID (cas_id);
1626+ if (!id)
1627+ return id.takeError ();
1628+
1629+ auto module_proxy = cas->getProxy (*id);
1630+ if (!module_proxy)
1631+ return module_proxy.takeError ();
1632+
1633+ // Create a temporary file that holds the module info.
1634+ llvm::SmallString<0 > name;
1635+ int fd;
1636+ auto ec =
1637+ llvm::sys::fs::createTemporaryFile (" lldb-module-cas" , " pcm" , fd, name);
1638+ if (ec || fd <= 0 )
1639+ return llvm::createStringError (
1640+ " could not create temporary file for module" );
1641+
1642+ NativeFile file (fd, File::eOpenOptionWriteOnly, true );
1643+ size_t num_bytes = module_proxy->getData ().size ();
1644+ file.Write (module_proxy->getData ().data (), num_bytes);
1645+
1646+ Log *log = GetLog (LLDBLog::Modules);
1647+ if (log != nullptr )
1648+ LLDB_LOGF (log, " loading module '%s' using CASID '%s' from temp file: %s" ,
1649+ module_name.AsCString (), cas_id, name.c_str ());
1650+
1651+ module_spec.GetFileSpec ().SetFile (name, FileSpec::Style::native);
1652+ return llvm::Error::success ();
1653+ }
1654+
1655+ Status ModuleList::GetSharedModuleFromCAS (ConstString module_name,
1656+ const char *cas_id, FileSpec cu_path,
1657+ ModuleSpec &module_spec,
1658+ lldb::ModuleSP &module_sp) {
1659+ auto err = loadModuleFromCAS (module_name, cas_id, cu_path, module_spec);
1660+ if (err)
1661+ return Status::FromErrorString (llvm::toString (std::move (err)).c_str ());
1662+
1663+ // Remove the temporary file created from CAS content after module is loaded.
1664+ auto cleanup_module = llvm::make_scope_exit ([&]() {
1665+ llvm::sys::fs::remove (
1666+ module_spec.GetFileSpec ().GetPathAsConstString ().GetStringRef ());
1667+ });
1668+
1669+ return GetSharedModule (module_spec, module_sp, nullptr , nullptr , nullptr );
1670+ }
1671+
15471672bool ModuleList::RemoveSharedModule (lldb::ModuleSP &module_sp) {
15481673 return GetSharedModuleList ().Remove (module_sp);
15491674}
0 commit comments