// Helper function: given a worklist and an index, will process all the worklist // and decide what to import based on the summary information. // // Nothing is actually imported, functions are materialized in their source // module and analyzed there. // // \p ModuleToFunctionsToImportMap is filled with the set of Function to import // per Module. static void GetImportList(Module &DestModule, SmallVector<StringRef, 64> &Worklist, StringSet<> &CalledFunctions, std::map<StringRef, DenseSet<const GlobalValue *>> &ModuleToFunctionsToImportMap, const FunctionInfoIndex &Index, ModuleLazyLoaderCache &ModuleLoaderCache) { while (!Worklist.empty()) { auto CalledFunctionName = Worklist.pop_back_val(); DEBUG(dbgs() << DestModule.getModuleIdentifier() << ": Process import for " << CalledFunctionName << "\n"); // Try to get a summary for this function call. auto InfoList = Index.findFunctionInfoList(CalledFunctionName); if (InfoList == Index.end()) { DEBUG(dbgs() << DestModule.getModuleIdentifier() << ": No summary for " << CalledFunctionName << " Ignoring.\n"); continue; } assert(!InfoList->second.empty() && "No summary, error at import?"); // Comdat can have multiple entries, FIXME: what do we do with them? auto &Info = InfoList->second[0]; assert(Info && "Nullptr in list, error importing summaries?\n"); auto *Summary = Info->functionSummary(); if (!Summary) { // FIXME: in case we are lazyloading summaries, we can do it now. DEBUG(dbgs() << DestModule.getModuleIdentifier() << ": Missing summary for " << CalledFunctionName << ", error at import?\n"); llvm_unreachable("Missing summary"); } if (Summary->instCount() > ImportInstrLimit) { DEBUG(dbgs() << DestModule.getModuleIdentifier() << ": Skip import of " << CalledFunctionName << " with " << Summary->instCount() << " instructions (limit " << ImportInstrLimit << ")\n"); continue; } // Get the module path from the summary. auto ModuleIdentifier = Summary->modulePath(); DEBUG(dbgs() << DestModule.getModuleIdentifier() << ": Importing " << CalledFunctionName << " from " << ModuleIdentifier << "\n"); auto &SrcModule = ModuleLoaderCache(ModuleIdentifier); // The function that we will import! GlobalValue *SGV = SrcModule.getNamedValue(CalledFunctionName); if (!SGV) { // The destination module is referencing function using their renamed name // when importing a function that was originally local in the source // module. The source module we have might not have been renamed so we try // to remove the suffix added during the renaming to recover the original // name in the source module. std::pair<StringRef, StringRef> Split = CalledFunctionName.split(".llvm."); SGV = SrcModule.getNamedValue(Split.first); assert(SGV && "Can't find function to import in source module"); } if (!SGV) { report_fatal_error(Twine("Can't load function '") + CalledFunctionName + "' in Module '" + SrcModule.getModuleIdentifier() + "', error in the summary?\n"); } Function *F = dyn_cast<Function>(SGV); if (!F && isa<GlobalAlias>(SGV)) { auto *SGA = dyn_cast<GlobalAlias>(SGV); F = dyn_cast<Function>(SGA->getBaseObject()); CalledFunctionName = F->getName(); } assert(F && "Imported Function is ... not a Function"); // We cannot import weak_any functions/aliases without possibly affecting // the order they are seen and selected by the linker, changing program // semantics. if (SGV->hasWeakAnyLinkage()) { DEBUG(dbgs() << DestModule.getModuleIdentifier() << ": Ignoring import request for weak-any " << (isa<Function>(SGV) ? "function " : "alias ") << CalledFunctionName << " from " << SrcModule.getModuleIdentifier() << "\n"); continue; } // Add the function to the import list auto &Entry = ModuleToFunctionsToImportMap[SrcModule.getModuleIdentifier()]; Entry.insert(F); // Process the newly imported functions and add callees to the worklist. F->materialize(); findExternalCalls(DestModule, *F, Index, CalledFunctions, Worklist); } }