142418abaSMehdi Amini //===- FunctionImport.cpp - ThinLTO Summary-based Function Import ---------===// 242418abaSMehdi Amini // 342418abaSMehdi Amini // The LLVM Compiler Infrastructure 442418abaSMehdi Amini // 542418abaSMehdi Amini // This file is distributed under the University of Illinois Open Source 642418abaSMehdi Amini // License. See LICENSE.TXT for details. 742418abaSMehdi Amini // 842418abaSMehdi Amini //===----------------------------------------------------------------------===// 942418abaSMehdi Amini // 1042418abaSMehdi Amini // This file implements Function import based on summaries. 1142418abaSMehdi Amini // 1242418abaSMehdi Amini //===----------------------------------------------------------------------===// 1342418abaSMehdi Amini 1442418abaSMehdi Amini #include "llvm/Transforms/IPO/FunctionImport.h" 1542418abaSMehdi Amini 1642418abaSMehdi Amini #include "llvm/ADT/StringSet.h" 1742418abaSMehdi Amini #include "llvm/IR/AutoUpgrade.h" 1842418abaSMehdi Amini #include "llvm/IR/DiagnosticPrinter.h" 1942418abaSMehdi Amini #include "llvm/IR/IntrinsicInst.h" 2042418abaSMehdi Amini #include "llvm/IR/Module.h" 2142418abaSMehdi Amini #include "llvm/IRReader/IRReader.h" 2242418abaSMehdi Amini #include "llvm/Linker/Linker.h" 2342418abaSMehdi Amini #include "llvm/Object/FunctionIndexObjectFile.h" 2442418abaSMehdi Amini #include "llvm/Support/CommandLine.h" 2542418abaSMehdi Amini #include "llvm/Support/Debug.h" 2642418abaSMehdi Amini #include "llvm/Support/SourceMgr.h" 277e88d0daSMehdi Amini 287e88d0daSMehdi Amini #include <map> 297e88d0daSMehdi Amini 3042418abaSMehdi Amini using namespace llvm; 3142418abaSMehdi Amini 3242418abaSMehdi Amini #define DEBUG_TYPE "function-import" 3342418abaSMehdi Amini 3439303619STeresa Johnson /// Limit on instruction count of imported functions. 3539303619STeresa Johnson static cl::opt<unsigned> ImportInstrLimit( 3639303619STeresa Johnson "import-instr-limit", cl::init(100), cl::Hidden, cl::value_desc("N"), 3739303619STeresa Johnson cl::desc("Only import functions with less than N instructions")); 3839303619STeresa Johnson 3942418abaSMehdi Amini // Load lazily a module from \p FileName in \p Context. 4042418abaSMehdi Amini static std::unique_ptr<Module> loadFile(const std::string &FileName, 4142418abaSMehdi Amini LLVMContext &Context) { 4242418abaSMehdi Amini SMDiagnostic Err; 4342418abaSMehdi Amini DEBUG(dbgs() << "Loading '" << FileName << "'\n"); 4442418abaSMehdi Amini std::unique_ptr<Module> Result = getLazyIRFileModule(FileName, Err, Context); 4542418abaSMehdi Amini if (!Result) { 4642418abaSMehdi Amini Err.print("function-import", errs()); 4742418abaSMehdi Amini return nullptr; 4842418abaSMehdi Amini } 4942418abaSMehdi Amini 5042418abaSMehdi Amini Result->materializeMetadata(); 5142418abaSMehdi Amini UpgradeDebugInfo(*Result); 5242418abaSMehdi Amini 5342418abaSMehdi Amini return Result; 5442418abaSMehdi Amini } 5542418abaSMehdi Amini 567e88d0daSMehdi Amini namespace { 577e88d0daSMehdi Amini /// Helper to load on demand a Module from file and cache it for subsequent 587e88d0daSMehdi Amini /// queries. It can be used with the FunctionImporter. 597e88d0daSMehdi Amini class ModuleLazyLoaderCache { 607e88d0daSMehdi Amini /// Cache of lazily loaded module for import. 617e88d0daSMehdi Amini StringMap<std::unique_ptr<Module>> ModuleMap; 627e88d0daSMehdi Amini 637e88d0daSMehdi Amini /// Retrieve a Module from the cache or lazily load it on demand. 647e88d0daSMehdi Amini std::function<std::unique_ptr<Module>(StringRef FileName)> createLazyModule; 657e88d0daSMehdi Amini 667e88d0daSMehdi Amini public: 677e88d0daSMehdi Amini /// Create the loader, Module will be initialized in \p Context. 687e88d0daSMehdi Amini ModuleLazyLoaderCache(std::function< 697e88d0daSMehdi Amini std::unique_ptr<Module>(StringRef FileName)> createLazyModule) 707e88d0daSMehdi Amini : createLazyModule(createLazyModule) {} 717e88d0daSMehdi Amini 727e88d0daSMehdi Amini /// Retrieve a Module from the cache or lazily load it on demand. 737e88d0daSMehdi Amini Module &operator()(StringRef FileName); 74434e9561SRafael Espindola 75434e9561SRafael Espindola std::unique_ptr<Module> takeModule(StringRef FileName) { 76434e9561SRafael Espindola auto I = ModuleMap.find(FileName); 77434e9561SRafael Espindola assert(I != ModuleMap.end()); 78434e9561SRafael Espindola std::unique_ptr<Module> Ret = std::move(I->second); 79434e9561SRafael Espindola ModuleMap.erase(I); 80434e9561SRafael Espindola return Ret; 81434e9561SRafael Espindola } 827e88d0daSMehdi Amini }; 837e88d0daSMehdi Amini 847e88d0daSMehdi Amini // Get a Module for \p FileName from the cache, or load it lazily. 857e88d0daSMehdi Amini Module &ModuleLazyLoaderCache::operator()(StringRef Identifier) { 867e88d0daSMehdi Amini auto &Module = ModuleMap[Identifier]; 877e88d0daSMehdi Amini if (!Module) 887e88d0daSMehdi Amini Module = createLazyModule(Identifier); 897e88d0daSMehdi Amini return *Module; 907e88d0daSMehdi Amini } 917e88d0daSMehdi Amini } // anonymous namespace 927e88d0daSMehdi Amini 93d450da32STeresa Johnson /// Walk through the instructions in \p F looking for external 94d450da32STeresa Johnson /// calls not already in the \p CalledFunctions set. If any are 95d450da32STeresa Johnson /// found they are added to the \p Worklist for importing. 967e88d0daSMehdi Amini static void findExternalCalls(const Module &DestModule, Function &F, 977e88d0daSMehdi Amini const FunctionInfoIndex &Index, 987e88d0daSMehdi Amini StringSet<> &CalledFunctions, 99d450da32STeresa Johnson SmallVector<StringRef, 64> &Worklist) { 1007e88d0daSMehdi Amini // We need to suffix internal function calls imported from other modules, 1017e88d0daSMehdi Amini // prepare the suffix ahead of time. 1029edc3b84SRafael Espindola std::string Suffix; 1037e88d0daSMehdi Amini if (F.getParent() != &DestModule) 1047e88d0daSMehdi Amini Suffix = 1057e88d0daSMehdi Amini (Twine(".llvm.") + 1067e88d0daSMehdi Amini Twine(Index.getModuleId(F.getParent()->getModuleIdentifier()))).str(); 1077e88d0daSMehdi Amini 108d450da32STeresa Johnson for (auto &BB : F) { 109d450da32STeresa Johnson for (auto &I : BB) { 110d450da32STeresa Johnson if (isa<CallInst>(I)) { 111d450da32STeresa Johnson auto CalledFunction = cast<CallInst>(I).getCalledFunction(); 112d450da32STeresa Johnson // Insert any new external calls that have not already been 113d450da32STeresa Johnson // added to set/worklist. 1147e88d0daSMehdi Amini if (!CalledFunction || !CalledFunction->hasName()) 1157e88d0daSMehdi Amini continue; 1167e88d0daSMehdi Amini // Ignore intrinsics early 1177e88d0daSMehdi Amini if (CalledFunction->isIntrinsic()) { 1187e88d0daSMehdi Amini assert(CalledFunction->getIntrinsicID() != 0); 1197e88d0daSMehdi Amini continue; 120d450da32STeresa Johnson } 1217e88d0daSMehdi Amini auto ImportedName = CalledFunction->getName(); 1227e88d0daSMehdi Amini auto Renamed = (ImportedName + Suffix).str(); 1237e88d0daSMehdi Amini // Rename internal functions 1247e88d0daSMehdi Amini if (CalledFunction->hasInternalLinkage()) { 1257e88d0daSMehdi Amini ImportedName = Renamed; 1267e88d0daSMehdi Amini } 1277e88d0daSMehdi Amini auto It = CalledFunctions.insert(ImportedName); 1287e88d0daSMehdi Amini if (!It.second) { 1297e88d0daSMehdi Amini // This is a call to a function we already considered, skip. 1307e88d0daSMehdi Amini continue; 1317e88d0daSMehdi Amini } 1327e88d0daSMehdi Amini // Ignore functions already present in the destination module 1337e88d0daSMehdi Amini auto *SrcGV = DestModule.getNamedValue(ImportedName); 1347e88d0daSMehdi Amini if (SrcGV) { 1357e88d0daSMehdi Amini assert(isa<Function>(SrcGV) && "Name collision during import"); 1367e88d0daSMehdi Amini if (!cast<Function>(SrcGV)->isDeclaration()) { 1379f2ff9c6STeresa Johnson DEBUG(dbgs() << DestModule.getModuleIdentifier() << ": Ignoring " 1387e88d0daSMehdi Amini << ImportedName << " already in DestinationModule\n"); 1397e88d0daSMehdi Amini continue; 1407e88d0daSMehdi Amini } 1417e88d0daSMehdi Amini } 1427e88d0daSMehdi Amini 1437e88d0daSMehdi Amini Worklist.push_back(It.first->getKey()); 1447e88d0daSMehdi Amini DEBUG(dbgs() << DestModule.getModuleIdentifier() 1459f2ff9c6STeresa Johnson << ": Adding callee for : " << ImportedName << " : " 1467e88d0daSMehdi Amini << F.getName() << "\n"); 147d450da32STeresa Johnson } 148d450da32STeresa Johnson } 149d450da32STeresa Johnson } 150d450da32STeresa Johnson } 151d450da32STeresa Johnson 152c8c55170SMehdi Amini // Helper function: given a worklist and an index, will process all the worklist 1537e88d0daSMehdi Amini // and decide what to import based on the summary information. 1547e88d0daSMehdi Amini // 1557e88d0daSMehdi Amini // Nothing is actually imported, functions are materialized in their source 1567e88d0daSMehdi Amini // module and analyzed there. 1577e88d0daSMehdi Amini // 1587e88d0daSMehdi Amini // \p ModuleToFunctionsToImportMap is filled with the set of Function to import 1597e88d0daSMehdi Amini // per Module. 160434e9561SRafael Espindola static void GetImportList(Module &DestModule, 161434e9561SRafael Espindola SmallVector<StringRef, 64> &Worklist, 1627e88d0daSMehdi Amini StringSet<> &CalledFunctions, 163434e9561SRafael Espindola std::map<StringRef, DenseSet<const GlobalValue *>> 164434e9561SRafael Espindola &ModuleToFunctionsToImportMap, 165434e9561SRafael Espindola const FunctionInfoIndex &Index, 166434e9561SRafael Espindola ModuleLazyLoaderCache &ModuleLoaderCache) { 16742418abaSMehdi Amini while (!Worklist.empty()) { 16842418abaSMehdi Amini auto CalledFunctionName = Worklist.pop_back_val(); 1699f2ff9c6STeresa Johnson DEBUG(dbgs() << DestModule.getModuleIdentifier() << ": Process import for " 1705411d051SMehdi Amini << CalledFunctionName << "\n"); 17142418abaSMehdi Amini 17242418abaSMehdi Amini // Try to get a summary for this function call. 17342418abaSMehdi Amini auto InfoList = Index.findFunctionInfoList(CalledFunctionName); 17442418abaSMehdi Amini if (InfoList == Index.end()) { 1759f2ff9c6STeresa Johnson DEBUG(dbgs() << DestModule.getModuleIdentifier() << ": No summary for " 1765411d051SMehdi Amini << CalledFunctionName << " Ignoring.\n"); 17742418abaSMehdi Amini continue; 17842418abaSMehdi Amini } 17942418abaSMehdi Amini assert(!InfoList->second.empty() && "No summary, error at import?"); 18042418abaSMehdi Amini 18142418abaSMehdi Amini // Comdat can have multiple entries, FIXME: what do we do with them? 18242418abaSMehdi Amini auto &Info = InfoList->second[0]; 18342418abaSMehdi Amini assert(Info && "Nullptr in list, error importing summaries?\n"); 18442418abaSMehdi Amini 18542418abaSMehdi Amini auto *Summary = Info->functionSummary(); 18642418abaSMehdi Amini if (!Summary) { 18742418abaSMehdi Amini // FIXME: in case we are lazyloading summaries, we can do it now. 1885411d051SMehdi Amini DEBUG(dbgs() << DestModule.getModuleIdentifier() 1899f2ff9c6STeresa Johnson << ": Missing summary for " << CalledFunctionName 190430110ccSTeresa Johnson << ", error at import?\n"); 19142418abaSMehdi Amini llvm_unreachable("Missing summary"); 19242418abaSMehdi Amini } 19342418abaSMehdi Amini 19439303619STeresa Johnson if (Summary->instCount() > ImportInstrLimit) { 1959f2ff9c6STeresa Johnson DEBUG(dbgs() << DestModule.getModuleIdentifier() << ": Skip import of " 1965411d051SMehdi Amini << CalledFunctionName << " with " << Summary->instCount() 1975411d051SMehdi Amini << " instructions (limit " << ImportInstrLimit << ")\n"); 19839303619STeresa Johnson continue; 19939303619STeresa Johnson } 20039303619STeresa Johnson 20142418abaSMehdi Amini // Get the module path from the summary. 2027e88d0daSMehdi Amini auto ModuleIdentifier = Summary->modulePath(); 2039f2ff9c6STeresa Johnson DEBUG(dbgs() << DestModule.getModuleIdentifier() << ": Importing " 2047e88d0daSMehdi Amini << CalledFunctionName << " from " << ModuleIdentifier << "\n"); 20542418abaSMehdi Amini 2067e88d0daSMehdi Amini auto &SrcModule = ModuleLoaderCache(ModuleIdentifier); 20742418abaSMehdi Amini 20842418abaSMehdi Amini // The function that we will import! 2097e88d0daSMehdi Amini GlobalValue *SGV = SrcModule.getNamedValue(CalledFunctionName); 2107e88d0daSMehdi Amini 211130de7afSTeresa Johnson if (!SGV) { 2127e88d0daSMehdi Amini // The destination module is referencing function using their renamed name 2137e88d0daSMehdi Amini // when importing a function that was originally local in the source 2147e88d0daSMehdi Amini // module. The source module we have might not have been renamed so we try 2157e88d0daSMehdi Amini // to remove the suffix added during the renaming to recover the original 2167e88d0daSMehdi Amini // name in the source module. 217130de7afSTeresa Johnson std::pair<StringRef, StringRef> Split = 218130de7afSTeresa Johnson CalledFunctionName.split(".llvm."); 2197e88d0daSMehdi Amini SGV = SrcModule.getNamedValue(Split.first); 2207e88d0daSMehdi Amini assert(SGV && "Can't find function to import in source module"); 221130de7afSTeresa Johnson } 2227e88d0daSMehdi Amini if (!SGV) { 2237e88d0daSMehdi Amini report_fatal_error(Twine("Can't load function '") + CalledFunctionName + 2247e88d0daSMehdi Amini "' in Module '" + SrcModule.getModuleIdentifier() + 2257e88d0daSMehdi Amini "', error in the summary?\n"); 2267e88d0daSMehdi Amini } 2277e88d0daSMehdi Amini 22842418abaSMehdi Amini Function *F = dyn_cast<Function>(SGV); 22942418abaSMehdi Amini if (!F && isa<GlobalAlias>(SGV)) { 23042418abaSMehdi Amini auto *SGA = dyn_cast<GlobalAlias>(SGV); 23142418abaSMehdi Amini F = dyn_cast<Function>(SGA->getBaseObject()); 2327e88d0daSMehdi Amini CalledFunctionName = F->getName(); 23342418abaSMehdi Amini } 2347e88d0daSMehdi Amini assert(F && "Imported Function is ... not a Function"); 23542418abaSMehdi Amini 23617626654STeresa Johnson // We cannot import weak_any functions/aliases without possibly affecting 23717626654STeresa Johnson // the order they are seen and selected by the linker, changing program 23842418abaSMehdi Amini // semantics. 23917626654STeresa Johnson if (SGV->hasWeakAnyLinkage()) { 2405411d051SMehdi Amini DEBUG(dbgs() << DestModule.getModuleIdentifier() 2419f2ff9c6STeresa Johnson << ": Ignoring import request for weak-any " 24217626654STeresa Johnson << (isa<Function>(SGV) ? "function " : "alias ") 2437e88d0daSMehdi Amini << CalledFunctionName << " from " 2447e88d0daSMehdi Amini << SrcModule.getModuleIdentifier() << "\n"); 24542418abaSMehdi Amini continue; 24642418abaSMehdi Amini } 24742418abaSMehdi Amini 2487e88d0daSMehdi Amini // Add the function to the import list 2497e88d0daSMehdi Amini auto &Entry = ModuleToFunctionsToImportMap[SrcModule.getModuleIdentifier()]; 250434e9561SRafael Espindola Entry.insert(F); 25142418abaSMehdi Amini 2527e88d0daSMehdi Amini // Process the newly imported functions and add callees to the worklist. 2537e88d0daSMehdi Amini F->materialize(); 2547e88d0daSMehdi Amini findExternalCalls(DestModule, *F, Index, CalledFunctions, Worklist); 255c8c55170SMehdi Amini } 25642418abaSMehdi Amini } 257ffe2e4aaSMehdi Amini 258c8c55170SMehdi Amini // Automatically import functions in Module \p DestModule based on the summaries 259c8c55170SMehdi Amini // index. 260c8c55170SMehdi Amini // 261c8c55170SMehdi Amini // The current implementation imports every called functions that exists in the 262c8c55170SMehdi Amini // summaries index. 263c8c55170SMehdi Amini bool FunctionImporter::importFunctions(Module &DestModule) { 2645411d051SMehdi Amini DEBUG(dbgs() << "Starting import for Module " 265311fef6eSMehdi Amini << DestModule.getModuleIdentifier() << "\n"); 266c8c55170SMehdi Amini unsigned ImportedCount = 0; 267c8c55170SMehdi Amini 268c8c55170SMehdi Amini /// First step is collecting the called external functions. 269c8c55170SMehdi Amini StringSet<> CalledFunctions; 270c8c55170SMehdi Amini SmallVector<StringRef, 64> Worklist; 271c8c55170SMehdi Amini for (auto &F : DestModule) { 272c8c55170SMehdi Amini if (F.isDeclaration() || F.hasFnAttribute(Attribute::OptimizeNone)) 273c8c55170SMehdi Amini continue; 2747e88d0daSMehdi Amini findExternalCalls(DestModule, F, Index, CalledFunctions, Worklist); 275c8c55170SMehdi Amini } 276c8c55170SMehdi Amini if (Worklist.empty()) 277c8c55170SMehdi Amini return false; 278c8c55170SMehdi Amini 279c8c55170SMehdi Amini /// Second step: for every call to an external function, try to import it. 280c8c55170SMehdi Amini 281c8c55170SMehdi Amini // Linker that will be used for importing function 2829d2bfc48SRafael Espindola Linker TheLinker(DestModule); 283c8c55170SMehdi Amini 2847e88d0daSMehdi Amini // Map of Module -> List of Function to import from the Module 285434e9561SRafael Espindola std::map<StringRef, DenseSet<const GlobalValue *>> 2867e88d0daSMehdi Amini ModuleToFunctionsToImportMap; 287c8c55170SMehdi Amini 2887e88d0daSMehdi Amini // Analyze the summaries and get the list of functions to import by 2897e88d0daSMehdi Amini // populating ModuleToFunctionsToImportMap 2907e88d0daSMehdi Amini ModuleLazyLoaderCache ModuleLoaderCache(ModuleLoader); 2917e88d0daSMehdi Amini GetImportList(DestModule, Worklist, CalledFunctions, 2927e88d0daSMehdi Amini ModuleToFunctionsToImportMap, Index, ModuleLoaderCache); 2937e88d0daSMehdi Amini assert(Worklist.empty() && "Worklist hasn't been flushed in GetImportList"); 2947e88d0daSMehdi Amini 295e5a61917STeresa Johnson StringMap<std::unique_ptr<DenseMap<unsigned, MDNode *>>> 296e5a61917STeresa Johnson ModuleToTempMDValsMap; 297e5a61917STeresa Johnson 2987e88d0daSMehdi Amini // Do the actual import of functions now, one Module at a time 2997e88d0daSMehdi Amini for (auto &FunctionsToImportPerModule : ModuleToFunctionsToImportMap) { 3007e88d0daSMehdi Amini // Get the module for the import 301434e9561SRafael Espindola auto &FunctionsToImport = FunctionsToImportPerModule.second; 302434e9561SRafael Espindola std::unique_ptr<Module> SrcModule = 303434e9561SRafael Espindola ModuleLoaderCache.takeModule(FunctionsToImportPerModule.first); 3047e88d0daSMehdi Amini assert(&DestModule.getContext() == &SrcModule->getContext() && 3057e88d0daSMehdi Amini "Context mismatch"); 3067e88d0daSMehdi Amini 307e5a61917STeresa Johnson // Save the mapping of value ids to temporary metadata created when 308e5a61917STeresa Johnson // importing this function. If we have already imported from this module, 309e5a61917STeresa Johnson // add new temporary metadata to the existing mapping. 310e5a61917STeresa Johnson auto &TempMDVals = ModuleToTempMDValsMap[SrcModule->getModuleIdentifier()]; 311e5a61917STeresa Johnson if (!TempMDVals) 312e5a61917STeresa Johnson TempMDVals = llvm::make_unique<DenseMap<unsigned, MDNode *>>(); 313e5a61917STeresa Johnson 3147e88d0daSMehdi Amini // Link in the specified functions. 315434e9561SRafael Espindola if (TheLinker.linkInModule(std::move(SrcModule), Linker::Flags::None, 316e5a61917STeresa Johnson &Index, &FunctionsToImport, TempMDVals.get())) 3177e88d0daSMehdi Amini report_fatal_error("Function Import: link error"); 3187e88d0daSMehdi Amini 3197e88d0daSMehdi Amini ImportedCount += FunctionsToImport.size(); 3207e88d0daSMehdi Amini } 321e5a61917STeresa Johnson 322e5a61917STeresa Johnson // Now link in metadata for all modules from which we imported functions. 323e5a61917STeresa Johnson for (StringMapEntry<std::unique_ptr<DenseMap<unsigned, MDNode *>>> &SME : 324e5a61917STeresa Johnson ModuleToTempMDValsMap) { 325e5a61917STeresa Johnson // Load the specified source module. 326e5a61917STeresa Johnson auto &SrcModule = ModuleLoaderCache(SME.getKey()); 327e5a61917STeresa Johnson 328e5a61917STeresa Johnson // Link in all necessary metadata from this module. 329e5a61917STeresa Johnson if (TheLinker.linkInMetadata(SrcModule, SME.getValue().get())) 330e5a61917STeresa Johnson return false; 331e5a61917STeresa Johnson } 332e5a61917STeresa Johnson 3337e88d0daSMehdi Amini DEBUG(dbgs() << "Imported " << ImportedCount << " functions for Module " 334c8c55170SMehdi Amini << DestModule.getModuleIdentifier() << "\n"); 335c8c55170SMehdi Amini return ImportedCount; 33642418abaSMehdi Amini } 33742418abaSMehdi Amini 33842418abaSMehdi Amini /// Summary file to use for function importing when using -function-import from 33942418abaSMehdi Amini /// the command line. 34042418abaSMehdi Amini static cl::opt<std::string> 34142418abaSMehdi Amini SummaryFile("summary-file", 34242418abaSMehdi Amini cl::desc("The summary file to use for function importing.")); 34342418abaSMehdi Amini 34442418abaSMehdi Amini static void diagnosticHandler(const DiagnosticInfo &DI) { 34542418abaSMehdi Amini raw_ostream &OS = errs(); 34642418abaSMehdi Amini DiagnosticPrinterRawOStream DP(OS); 34742418abaSMehdi Amini DI.print(DP); 34842418abaSMehdi Amini OS << '\n'; 34942418abaSMehdi Amini } 35042418abaSMehdi Amini 35142418abaSMehdi Amini /// Parse the function index out of an IR file and return the function 35242418abaSMehdi Amini /// index object if found, or nullptr if not. 35342418abaSMehdi Amini static std::unique_ptr<FunctionInfoIndex> 35442418abaSMehdi Amini getFunctionIndexForFile(StringRef Path, std::string &Error, 35542418abaSMehdi Amini DiagnosticHandlerFunction DiagnosticHandler) { 35642418abaSMehdi Amini std::unique_ptr<MemoryBuffer> Buffer; 35742418abaSMehdi Amini ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = 35842418abaSMehdi Amini MemoryBuffer::getFile(Path); 35942418abaSMehdi Amini if (std::error_code EC = BufferOrErr.getError()) { 36042418abaSMehdi Amini Error = EC.message(); 36142418abaSMehdi Amini return nullptr; 36242418abaSMehdi Amini } 36342418abaSMehdi Amini Buffer = std::move(BufferOrErr.get()); 36442418abaSMehdi Amini ErrorOr<std::unique_ptr<object::FunctionIndexObjectFile>> ObjOrErr = 36542418abaSMehdi Amini object::FunctionIndexObjectFile::create(Buffer->getMemBufferRef(), 36642418abaSMehdi Amini DiagnosticHandler); 36742418abaSMehdi Amini if (std::error_code EC = ObjOrErr.getError()) { 36842418abaSMehdi Amini Error = EC.message(); 36942418abaSMehdi Amini return nullptr; 37042418abaSMehdi Amini } 37142418abaSMehdi Amini return (*ObjOrErr)->takeIndex(); 37242418abaSMehdi Amini } 37342418abaSMehdi Amini 374*fe2b5415SBenjamin Kramer namespace { 37542418abaSMehdi Amini /// Pass that performs cross-module function import provided a summary file. 37642418abaSMehdi Amini class FunctionImportPass : public ModulePass { 3775fcbdb71STeresa Johnson /// Optional function summary index to use for importing, otherwise 3785fcbdb71STeresa Johnson /// the summary-file option must be specified. 3797f961e14STeresa Johnson const FunctionInfoIndex *Index; 38042418abaSMehdi Amini 38142418abaSMehdi Amini public: 38242418abaSMehdi Amini /// Pass identification, replacement for typeid 38342418abaSMehdi Amini static char ID; 38442418abaSMehdi Amini 3855fcbdb71STeresa Johnson /// Specify pass name for debug output 3865fcbdb71STeresa Johnson const char *getPassName() const override { 3875fcbdb71STeresa Johnson return "Function Importing"; 3885fcbdb71STeresa Johnson } 3895fcbdb71STeresa Johnson 3907f961e14STeresa Johnson explicit FunctionImportPass(const FunctionInfoIndex *Index = nullptr) 3915fcbdb71STeresa Johnson : ModulePass(ID), Index(Index) {} 39242418abaSMehdi Amini 39342418abaSMehdi Amini bool runOnModule(Module &M) override { 3945fcbdb71STeresa Johnson if (SummaryFile.empty() && !Index) 3955fcbdb71STeresa Johnson report_fatal_error("error: -function-import requires -summary-file or " 3965fcbdb71STeresa Johnson "file from frontend\n"); 3975fcbdb71STeresa Johnson std::unique_ptr<FunctionInfoIndex> IndexPtr; 3985fcbdb71STeresa Johnson if (!SummaryFile.empty()) { 3995fcbdb71STeresa Johnson if (Index) 4005fcbdb71STeresa Johnson report_fatal_error("error: -summary-file and index from frontend\n"); 40142418abaSMehdi Amini std::string Error; 4025fcbdb71STeresa Johnson IndexPtr = getFunctionIndexForFile(SummaryFile, Error, diagnosticHandler); 4035fcbdb71STeresa Johnson if (!IndexPtr) { 4045fcbdb71STeresa Johnson errs() << "Error loading file '" << SummaryFile << "': " << Error 4055fcbdb71STeresa Johnson << "\n"; 40642418abaSMehdi Amini return false; 40742418abaSMehdi Amini } 4085fcbdb71STeresa Johnson Index = IndexPtr.get(); 4095fcbdb71STeresa Johnson } 41042418abaSMehdi Amini 41142418abaSMehdi Amini // Perform the import now. 412d16c8065SMehdi Amini auto ModuleLoader = [&M](StringRef Identifier) { 413d16c8065SMehdi Amini return loadFile(Identifier, M.getContext()); 414d16c8065SMehdi Amini }; 4159d2bfc48SRafael Espindola FunctionImporter Importer(*Index, ModuleLoader); 41642418abaSMehdi Amini return Importer.importFunctions(M); 41742418abaSMehdi Amini 41842418abaSMehdi Amini return false; 41942418abaSMehdi Amini } 42042418abaSMehdi Amini }; 421*fe2b5415SBenjamin Kramer } // anonymous namespace 42242418abaSMehdi Amini 42342418abaSMehdi Amini char FunctionImportPass::ID = 0; 42442418abaSMehdi Amini INITIALIZE_PASS_BEGIN(FunctionImportPass, "function-import", 42542418abaSMehdi Amini "Summary Based Function Import", false, false) 42642418abaSMehdi Amini INITIALIZE_PASS_END(FunctionImportPass, "function-import", 42742418abaSMehdi Amini "Summary Based Function Import", false, false) 42842418abaSMehdi Amini 42942418abaSMehdi Amini namespace llvm { 4307f961e14STeresa Johnson Pass *createFunctionImportPass(const FunctionInfoIndex *Index = nullptr) { 4315fcbdb71STeresa Johnson return new FunctionImportPass(Index); 4325fcbdb71STeresa Johnson } 43342418abaSMehdi Amini } 434