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, {});
@@ -1248,8 +1278,11 @@ class SharedModuleList {
12481278struct SharedModuleListInfo {
12491279 ModuleList module_list;
12501280 ModuleListProperties module_list_properties;
1281+ std::shared_ptr<llvm::cas::ObjectStore> cas_object_store;
1282+ std::mutex shared_lock;
12511283};
12521284}
1285+
12531286static SharedModuleListInfo &GetSharedModuleListInfo ()
12541287{
12551288 static SharedModuleListInfo *g_shared_module_list_info = nullptr ;
@@ -1268,6 +1301,45 @@ static ModuleList &GetSharedModuleList() {
12681301 return GetSharedModuleListInfo ().module_list ;
12691302}
12701303
1304+ static std::shared_ptr<llvm::cas::ObjectStore>
1305+ GetOrCreateCASStorage (FileSpec CandidateConfigSearchPath) {
1306+ auto &shared_module_list = GetSharedModuleListInfo ();
1307+ if (shared_module_list.cas_object_store )
1308+ return shared_module_list.cas_object_store ;
1309+
1310+ std::scoped_lock<std::mutex> lock (shared_module_list.shared_lock );
1311+ // Config CAS from properties.
1312+ llvm::cas::CASConfiguration cas_config;
1313+ cas_config.CASPath =
1314+ ModuleList::GetGlobalModuleListProperties ().GetCASOnDiskPath ().GetPath ();
1315+ cas_config.PluginPath =
1316+ ModuleList::GetGlobalModuleListProperties ().GetCASPluginPath ().GetPath ();
1317+ cas_config.PluginOptions =
1318+ ModuleList::GetGlobalModuleListProperties ().GetCASPluginOptions ();
1319+
1320+ if (!cas_config.CASPath .empty ()) {
1321+ if (auto maybe_cas = cas_config.createDatabases ()) {
1322+ shared_module_list.cas_object_store = std::move (maybe_cas->first );
1323+ return shared_module_list.cas_object_store ;
1324+ } else
1325+ llvm::consumeError (maybe_cas.takeError ());
1326+ }
1327+
1328+ // Try search from candidiate path.
1329+ auto search_config = llvm::cas::CASConfiguration::createFromSearchConfigFile (
1330+ CandidateConfigSearchPath.GetPath ());
1331+ if (!search_config)
1332+ return nullptr ;
1333+
1334+ if (auto maybe_cas = search_config->second .createDatabases ()) {
1335+ shared_module_list.cas_object_store = std::move (maybe_cas->first );
1336+ return shared_module_list.cas_object_store ;
1337+ } else
1338+ llvm::consumeError (maybe_cas.takeError ());
1339+
1340+ return nullptr ;
1341+ }
1342+
12711343ModuleListProperties &ModuleList::GetGlobalModuleListProperties () {
12721344 return GetSharedModuleListInfo ().module_list_properties ;
12731345}
@@ -1540,6 +1612,59 @@ ModuleList::GetSharedModule(const ModuleSpec &module_spec, ModuleSP &module_sp,
15401612 return error;
15411613}
15421614
1615+ static llvm::Error loadModuleFromCAS (ConstString module_name,
1616+ const char *cas_id, FileSpec cu_path,
1617+ ModuleSpec &module_spec) {
1618+ auto cas = GetOrCreateCASStorage (cu_path);
1619+ if (!cas)
1620+ return llvm::createStringError (" CAS is not available" );
1621+ auto id = cas->parseID (cas_id);
1622+ if (!id)
1623+ return id.takeError ();
1624+
1625+ auto module_proxy = cas->getProxy (*id);
1626+ if (!module_proxy)
1627+ return module_proxy.takeError ();
1628+
1629+ // Create a temporary file that holds the module info.
1630+ llvm::SmallString<0 > name;
1631+ int fd;
1632+ auto ec =
1633+ llvm::sys::fs::createTemporaryFile (" lldb-module-cas" , " pcm" , fd, name);
1634+ if (ec || fd <= 0 )
1635+ return llvm::createStringError (
1636+ " could not create temporary file for module" );
1637+
1638+ NativeFile file (fd, File::eOpenOptionWriteOnly, true );
1639+ size_t num_bytes = module_proxy->getData ().size ();
1640+ file.Write (module_proxy->getData ().data (), num_bytes);
1641+
1642+ Log *log = GetLog (LLDBLog::Modules);
1643+ if (log != nullptr )
1644+ LLDB_LOGF (log, " loading module '%s' using CASID '%s' from temp file: %s" ,
1645+ module_name.AsCString (), cas_id, name.c_str ());
1646+
1647+ module_spec.GetFileSpec ().SetFile (name, FileSpec::Style::native);
1648+ return llvm::Error::success ();
1649+ }
1650+
1651+ Status ModuleList::GetSharedModuleFromCAS (ConstString module_name,
1652+ const char *cas_id, FileSpec cu_path,
1653+ ModuleSpec &module_spec,
1654+ lldb::ModuleSP &module_sp) {
1655+ auto err = loadModuleFromCAS (module_name, cas_id, cu_path, module_spec);
1656+ if (err)
1657+ return Status::FromErrorString (llvm::toString (std::move (err)).c_str ());
1658+
1659+ // Remove the temporary file created from CAS content after module is loaded.
1660+ auto cleanup_module = llvm::make_scope_exit ([&]() {
1661+ llvm::sys::fs::remove (
1662+ module_spec.GetFileSpec ().GetPathAsConstString ().GetStringRef ());
1663+ });
1664+
1665+ return GetSharedModule (module_spec, module_sp, nullptr , nullptr , nullptr );
1666+ }
1667+
15431668bool ModuleList::RemoveSharedModule (lldb::ModuleSP &module_sp) {
15441669 return GetSharedModuleList ().Remove (module_sp);
15451670}
0 commit comments