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); 747e88d0daSMehdi Amini }; 757e88d0daSMehdi Amini 767e88d0daSMehdi Amini // Get a Module for \p FileName from the cache, or load it lazily. 777e88d0daSMehdi Amini Module &ModuleLazyLoaderCache::operator()(StringRef Identifier) { 787e88d0daSMehdi Amini auto &Module = ModuleMap[Identifier]; 797e88d0daSMehdi Amini if (!Module) 807e88d0daSMehdi Amini Module = createLazyModule(Identifier); 817e88d0daSMehdi Amini return *Module; 827e88d0daSMehdi Amini } 837e88d0daSMehdi Amini } // anonymous namespace 847e88d0daSMehdi Amini 85d450da32STeresa Johnson /// Walk through the instructions in \p F looking for external 86d450da32STeresa Johnson /// calls not already in the \p CalledFunctions set. If any are 87d450da32STeresa Johnson /// found they are added to the \p Worklist for importing. 887e88d0daSMehdi Amini static void findExternalCalls(const Module &DestModule, Function &F, 897e88d0daSMehdi Amini const FunctionInfoIndex &Index, 907e88d0daSMehdi Amini StringSet<> &CalledFunctions, 91d450da32STeresa Johnson SmallVector<StringRef, 64> &Worklist) { 927e88d0daSMehdi Amini // We need to suffix internal function calls imported from other modules, 937e88d0daSMehdi Amini // prepare the suffix ahead of time. 949edc3b84SRafael Espindola std::string Suffix; 957e88d0daSMehdi Amini if (F.getParent() != &DestModule) 967e88d0daSMehdi Amini Suffix = 977e88d0daSMehdi Amini (Twine(".llvm.") + 987e88d0daSMehdi Amini Twine(Index.getModuleId(F.getParent()->getModuleIdentifier()))).str(); 997e88d0daSMehdi Amini 100d450da32STeresa Johnson for (auto &BB : F) { 101d450da32STeresa Johnson for (auto &I : BB) { 102d450da32STeresa Johnson if (isa<CallInst>(I)) { 103d450da32STeresa Johnson auto CalledFunction = cast<CallInst>(I).getCalledFunction(); 104d450da32STeresa Johnson // Insert any new external calls that have not already been 105d450da32STeresa Johnson // added to set/worklist. 1067e88d0daSMehdi Amini if (!CalledFunction || !CalledFunction->hasName()) 1077e88d0daSMehdi Amini continue; 1087e88d0daSMehdi Amini // Ignore intrinsics early 1097e88d0daSMehdi Amini if (CalledFunction->isIntrinsic()) { 1107e88d0daSMehdi Amini assert(CalledFunction->getIntrinsicID() != 0); 1117e88d0daSMehdi Amini continue; 112d450da32STeresa Johnson } 1137e88d0daSMehdi Amini auto ImportedName = CalledFunction->getName(); 1147e88d0daSMehdi Amini auto Renamed = (ImportedName + Suffix).str(); 1157e88d0daSMehdi Amini // Rename internal functions 1167e88d0daSMehdi Amini if (CalledFunction->hasInternalLinkage()) { 1177e88d0daSMehdi Amini ImportedName = Renamed; 1187e88d0daSMehdi Amini } 1197e88d0daSMehdi Amini auto It = CalledFunctions.insert(ImportedName); 1207e88d0daSMehdi Amini if (!It.second) { 1217e88d0daSMehdi Amini // This is a call to a function we already considered, skip. 1227e88d0daSMehdi Amini continue; 1237e88d0daSMehdi Amini } 1247e88d0daSMehdi Amini // Ignore functions already present in the destination module 1257e88d0daSMehdi Amini auto *SrcGV = DestModule.getNamedValue(ImportedName); 1267e88d0daSMehdi Amini if (SrcGV) { 1277e88d0daSMehdi Amini assert(isa<Function>(SrcGV) && "Name collision during import"); 1287e88d0daSMehdi Amini if (!cast<Function>(SrcGV)->isDeclaration()) { 1299f2ff9c6STeresa Johnson DEBUG(dbgs() << DestModule.getModuleIdentifier() << ": Ignoring " 1307e88d0daSMehdi Amini << ImportedName << " already in DestinationModule\n"); 1317e88d0daSMehdi Amini continue; 1327e88d0daSMehdi Amini } 1337e88d0daSMehdi Amini } 1347e88d0daSMehdi Amini 1357e88d0daSMehdi Amini Worklist.push_back(It.first->getKey()); 1367e88d0daSMehdi Amini DEBUG(dbgs() << DestModule.getModuleIdentifier() 1379f2ff9c6STeresa Johnson << ": Adding callee for : " << ImportedName << " : " 1387e88d0daSMehdi Amini << F.getName() << "\n"); 139d450da32STeresa Johnson } 140d450da32STeresa Johnson } 141d450da32STeresa Johnson } 142d450da32STeresa Johnson } 143d450da32STeresa Johnson 144c8c55170SMehdi Amini // Helper function: given a worklist and an index, will process all the worklist 1457e88d0daSMehdi Amini // and decide what to import based on the summary information. 1467e88d0daSMehdi Amini // 1477e88d0daSMehdi Amini // Nothing is actually imported, functions are materialized in their source 1487e88d0daSMehdi Amini // module and analyzed there. 1497e88d0daSMehdi Amini // 1507e88d0daSMehdi Amini // \p ModuleToFunctionsToImportMap is filled with the set of Function to import 1517e88d0daSMehdi Amini // per Module. 1527e88d0daSMehdi Amini static void GetImportList( 153311fef6eSMehdi Amini Module &DestModule, SmallVector<StringRef, 64> &Worklist, 1547e88d0daSMehdi Amini StringSet<> &CalledFunctions, 1557e88d0daSMehdi Amini std::map<StringRef, std::pair<Module *, DenseSet<const GlobalValue *>>> & 1567e88d0daSMehdi Amini ModuleToFunctionsToImportMap, 1577e88d0daSMehdi Amini const FunctionInfoIndex &Index, ModuleLazyLoaderCache &ModuleLoaderCache) { 15842418abaSMehdi Amini while (!Worklist.empty()) { 15942418abaSMehdi Amini auto CalledFunctionName = Worklist.pop_back_val(); 1609f2ff9c6STeresa Johnson DEBUG(dbgs() << DestModule.getModuleIdentifier() << ": Process import for " 1615411d051SMehdi Amini << CalledFunctionName << "\n"); 16242418abaSMehdi Amini 16342418abaSMehdi Amini // Try to get a summary for this function call. 16442418abaSMehdi Amini auto InfoList = Index.findFunctionInfoList(CalledFunctionName); 16542418abaSMehdi Amini if (InfoList == Index.end()) { 1669f2ff9c6STeresa Johnson DEBUG(dbgs() << DestModule.getModuleIdentifier() << ": No summary for " 1675411d051SMehdi Amini << CalledFunctionName << " Ignoring.\n"); 16842418abaSMehdi Amini continue; 16942418abaSMehdi Amini } 17042418abaSMehdi Amini assert(!InfoList->second.empty() && "No summary, error at import?"); 17142418abaSMehdi Amini 17242418abaSMehdi Amini // Comdat can have multiple entries, FIXME: what do we do with them? 17342418abaSMehdi Amini auto &Info = InfoList->second[0]; 17442418abaSMehdi Amini assert(Info && "Nullptr in list, error importing summaries?\n"); 17542418abaSMehdi Amini 17642418abaSMehdi Amini auto *Summary = Info->functionSummary(); 17742418abaSMehdi Amini if (!Summary) { 17842418abaSMehdi Amini // FIXME: in case we are lazyloading summaries, we can do it now. 1795411d051SMehdi Amini DEBUG(dbgs() << DestModule.getModuleIdentifier() 1809f2ff9c6STeresa Johnson << ": Missing summary for " << CalledFunctionName 181430110ccSTeresa Johnson << ", error at import?\n"); 18242418abaSMehdi Amini llvm_unreachable("Missing summary"); 18342418abaSMehdi Amini } 18442418abaSMehdi Amini 18539303619STeresa Johnson if (Summary->instCount() > ImportInstrLimit) { 1869f2ff9c6STeresa Johnson DEBUG(dbgs() << DestModule.getModuleIdentifier() << ": Skip import of " 1875411d051SMehdi Amini << CalledFunctionName << " with " << Summary->instCount() 1885411d051SMehdi Amini << " instructions (limit " << ImportInstrLimit << ")\n"); 18939303619STeresa Johnson continue; 19039303619STeresa Johnson } 19139303619STeresa Johnson 19242418abaSMehdi Amini // Get the module path from the summary. 1937e88d0daSMehdi Amini auto ModuleIdentifier = Summary->modulePath(); 1949f2ff9c6STeresa Johnson DEBUG(dbgs() << DestModule.getModuleIdentifier() << ": Importing " 1957e88d0daSMehdi Amini << CalledFunctionName << " from " << ModuleIdentifier << "\n"); 19642418abaSMehdi Amini 1977e88d0daSMehdi Amini auto &SrcModule = ModuleLoaderCache(ModuleIdentifier); 19842418abaSMehdi Amini 19942418abaSMehdi Amini // The function that we will import! 2007e88d0daSMehdi Amini GlobalValue *SGV = SrcModule.getNamedValue(CalledFunctionName); 2017e88d0daSMehdi Amini 202130de7afSTeresa Johnson if (!SGV) { 2037e88d0daSMehdi Amini // The destination module is referencing function using their renamed name 2047e88d0daSMehdi Amini // when importing a function that was originally local in the source 2057e88d0daSMehdi Amini // module. The source module we have might not have been renamed so we try 2067e88d0daSMehdi Amini // to remove the suffix added during the renaming to recover the original 2077e88d0daSMehdi Amini // name in the source module. 208130de7afSTeresa Johnson std::pair<StringRef, StringRef> Split = 209130de7afSTeresa Johnson CalledFunctionName.split(".llvm."); 2107e88d0daSMehdi Amini SGV = SrcModule.getNamedValue(Split.first); 2117e88d0daSMehdi Amini assert(SGV && "Can't find function to import in source module"); 212130de7afSTeresa Johnson } 2137e88d0daSMehdi Amini if (!SGV) { 2147e88d0daSMehdi Amini report_fatal_error(Twine("Can't load function '") + CalledFunctionName + 2157e88d0daSMehdi Amini "' in Module '" + SrcModule.getModuleIdentifier() + 2167e88d0daSMehdi Amini "', error in the summary?\n"); 2177e88d0daSMehdi Amini } 2187e88d0daSMehdi Amini 21942418abaSMehdi Amini Function *F = dyn_cast<Function>(SGV); 22042418abaSMehdi Amini if (!F && isa<GlobalAlias>(SGV)) { 22142418abaSMehdi Amini auto *SGA = dyn_cast<GlobalAlias>(SGV); 22242418abaSMehdi Amini F = dyn_cast<Function>(SGA->getBaseObject()); 2237e88d0daSMehdi Amini CalledFunctionName = F->getName(); 22442418abaSMehdi Amini } 2257e88d0daSMehdi Amini assert(F && "Imported Function is ... not a Function"); 22642418abaSMehdi Amini 22717626654STeresa Johnson // We cannot import weak_any functions/aliases without possibly affecting 22817626654STeresa Johnson // the order they are seen and selected by the linker, changing program 22942418abaSMehdi Amini // semantics. 23017626654STeresa Johnson if (SGV->hasWeakAnyLinkage()) { 2315411d051SMehdi Amini DEBUG(dbgs() << DestModule.getModuleIdentifier() 2329f2ff9c6STeresa Johnson << ": Ignoring import request for weak-any " 23317626654STeresa Johnson << (isa<Function>(SGV) ? "function " : "alias ") 2347e88d0daSMehdi Amini << CalledFunctionName << " from " 2357e88d0daSMehdi Amini << SrcModule.getModuleIdentifier() << "\n"); 23642418abaSMehdi Amini continue; 23742418abaSMehdi Amini } 23842418abaSMehdi Amini 2397e88d0daSMehdi Amini // Add the function to the import list 2407e88d0daSMehdi Amini auto &Entry = ModuleToFunctionsToImportMap[SrcModule.getModuleIdentifier()]; 2417e88d0daSMehdi Amini Entry.first = &SrcModule; 2427e88d0daSMehdi Amini Entry.second.insert(F); 24342418abaSMehdi Amini 2447e88d0daSMehdi Amini // Process the newly imported functions and add callees to the worklist. 2457e88d0daSMehdi Amini F->materialize(); 2467e88d0daSMehdi Amini findExternalCalls(DestModule, *F, Index, CalledFunctions, Worklist); 247c8c55170SMehdi Amini } 24842418abaSMehdi Amini } 249ffe2e4aaSMehdi Amini 250c8c55170SMehdi Amini // Automatically import functions in Module \p DestModule based on the summaries 251c8c55170SMehdi Amini // index. 252c8c55170SMehdi Amini // 253c8c55170SMehdi Amini // The current implementation imports every called functions that exists in the 254c8c55170SMehdi Amini // summaries index. 255c8c55170SMehdi Amini bool FunctionImporter::importFunctions(Module &DestModule) { 2565411d051SMehdi Amini DEBUG(dbgs() << "Starting import for Module " 257311fef6eSMehdi Amini << DestModule.getModuleIdentifier() << "\n"); 258c8c55170SMehdi Amini unsigned ImportedCount = 0; 259c8c55170SMehdi Amini 260c8c55170SMehdi Amini /// First step is collecting the called external functions. 261c8c55170SMehdi Amini StringSet<> CalledFunctions; 262c8c55170SMehdi Amini SmallVector<StringRef, 64> Worklist; 263c8c55170SMehdi Amini for (auto &F : DestModule) { 264c8c55170SMehdi Amini if (F.isDeclaration() || F.hasFnAttribute(Attribute::OptimizeNone)) 265c8c55170SMehdi Amini continue; 2667e88d0daSMehdi Amini findExternalCalls(DestModule, F, Index, CalledFunctions, Worklist); 267c8c55170SMehdi Amini } 268c8c55170SMehdi Amini if (Worklist.empty()) 269c8c55170SMehdi Amini return false; 270c8c55170SMehdi Amini 271c8c55170SMehdi Amini /// Second step: for every call to an external function, try to import it. 272c8c55170SMehdi Amini 273c8c55170SMehdi Amini // Linker that will be used for importing function 274*9d2bfc48SRafael Espindola Linker TheLinker(DestModule); 275c8c55170SMehdi Amini 2767e88d0daSMehdi Amini // Map of Module -> List of Function to import from the Module 2777e88d0daSMehdi Amini std::map<StringRef, std::pair<Module *, DenseSet<const GlobalValue *>>> 2787e88d0daSMehdi Amini ModuleToFunctionsToImportMap; 279c8c55170SMehdi Amini 2807e88d0daSMehdi Amini // Analyze the summaries and get the list of functions to import by 2817e88d0daSMehdi Amini // populating ModuleToFunctionsToImportMap 2827e88d0daSMehdi Amini ModuleLazyLoaderCache ModuleLoaderCache(ModuleLoader); 2837e88d0daSMehdi Amini GetImportList(DestModule, Worklist, CalledFunctions, 2847e88d0daSMehdi Amini ModuleToFunctionsToImportMap, Index, ModuleLoaderCache); 2857e88d0daSMehdi Amini assert(Worklist.empty() && "Worklist hasn't been flushed in GetImportList"); 2867e88d0daSMehdi Amini 2877e88d0daSMehdi Amini // Do the actual import of functions now, one Module at a time 2887e88d0daSMehdi Amini for (auto &FunctionsToImportPerModule : ModuleToFunctionsToImportMap) { 2897e88d0daSMehdi Amini // Get the module for the import 2907e88d0daSMehdi Amini auto &FunctionsToImport = FunctionsToImportPerModule.second.second; 2917e88d0daSMehdi Amini auto *SrcModule = FunctionsToImportPerModule.second.first; 2927e88d0daSMehdi Amini assert(&DestModule.getContext() == &SrcModule->getContext() && 2937e88d0daSMehdi Amini "Context mismatch"); 2947e88d0daSMehdi Amini 2957e88d0daSMehdi Amini // Link in the specified functions. 2967e88d0daSMehdi Amini if (TheLinker.linkInModule(*SrcModule, Linker::Flags::None, &Index, 2977e88d0daSMehdi Amini &FunctionsToImport)) 2987e88d0daSMehdi Amini report_fatal_error("Function Import: link error"); 2997e88d0daSMehdi Amini 3007e88d0daSMehdi Amini ImportedCount += FunctionsToImport.size(); 3017e88d0daSMehdi Amini } 3027e88d0daSMehdi Amini DEBUG(dbgs() << "Imported " << ImportedCount << " functions for Module " 303c8c55170SMehdi Amini << DestModule.getModuleIdentifier() << "\n"); 304c8c55170SMehdi Amini return ImportedCount; 30542418abaSMehdi Amini } 30642418abaSMehdi Amini 30742418abaSMehdi Amini /// Summary file to use for function importing when using -function-import from 30842418abaSMehdi Amini /// the command line. 30942418abaSMehdi Amini static cl::opt<std::string> 31042418abaSMehdi Amini SummaryFile("summary-file", 31142418abaSMehdi Amini cl::desc("The summary file to use for function importing.")); 31242418abaSMehdi Amini 31342418abaSMehdi Amini static void diagnosticHandler(const DiagnosticInfo &DI) { 31442418abaSMehdi Amini raw_ostream &OS = errs(); 31542418abaSMehdi Amini DiagnosticPrinterRawOStream DP(OS); 31642418abaSMehdi Amini DI.print(DP); 31742418abaSMehdi Amini OS << '\n'; 31842418abaSMehdi Amini } 31942418abaSMehdi Amini 32042418abaSMehdi Amini /// Parse the function index out of an IR file and return the function 32142418abaSMehdi Amini /// index object if found, or nullptr if not. 32242418abaSMehdi Amini static std::unique_ptr<FunctionInfoIndex> 32342418abaSMehdi Amini getFunctionIndexForFile(StringRef Path, std::string &Error, 32442418abaSMehdi Amini DiagnosticHandlerFunction DiagnosticHandler) { 32542418abaSMehdi Amini std::unique_ptr<MemoryBuffer> Buffer; 32642418abaSMehdi Amini ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = 32742418abaSMehdi Amini MemoryBuffer::getFile(Path); 32842418abaSMehdi Amini if (std::error_code EC = BufferOrErr.getError()) { 32942418abaSMehdi Amini Error = EC.message(); 33042418abaSMehdi Amini return nullptr; 33142418abaSMehdi Amini } 33242418abaSMehdi Amini Buffer = std::move(BufferOrErr.get()); 33342418abaSMehdi Amini ErrorOr<std::unique_ptr<object::FunctionIndexObjectFile>> ObjOrErr = 33442418abaSMehdi Amini object::FunctionIndexObjectFile::create(Buffer->getMemBufferRef(), 33542418abaSMehdi Amini DiagnosticHandler); 33642418abaSMehdi Amini if (std::error_code EC = ObjOrErr.getError()) { 33742418abaSMehdi Amini Error = EC.message(); 33842418abaSMehdi Amini return nullptr; 33942418abaSMehdi Amini } 34042418abaSMehdi Amini return (*ObjOrErr)->takeIndex(); 34142418abaSMehdi Amini } 34242418abaSMehdi Amini 34342418abaSMehdi Amini /// Pass that performs cross-module function import provided a summary file. 34442418abaSMehdi Amini class FunctionImportPass : public ModulePass { 3455fcbdb71STeresa Johnson /// Optional function summary index to use for importing, otherwise 3465fcbdb71STeresa Johnson /// the summary-file option must be specified. 3477f961e14STeresa Johnson const FunctionInfoIndex *Index; 34842418abaSMehdi Amini 34942418abaSMehdi Amini public: 35042418abaSMehdi Amini /// Pass identification, replacement for typeid 35142418abaSMehdi Amini static char ID; 35242418abaSMehdi Amini 3535fcbdb71STeresa Johnson /// Specify pass name for debug output 3545fcbdb71STeresa Johnson const char *getPassName() const override { 3555fcbdb71STeresa Johnson return "Function Importing"; 3565fcbdb71STeresa Johnson } 3575fcbdb71STeresa Johnson 3587f961e14STeresa Johnson explicit FunctionImportPass(const FunctionInfoIndex *Index = nullptr) 3595fcbdb71STeresa Johnson : ModulePass(ID), Index(Index) {} 36042418abaSMehdi Amini 36142418abaSMehdi Amini bool runOnModule(Module &M) override { 3625fcbdb71STeresa Johnson if (SummaryFile.empty() && !Index) 3635fcbdb71STeresa Johnson report_fatal_error("error: -function-import requires -summary-file or " 3645fcbdb71STeresa Johnson "file from frontend\n"); 3655fcbdb71STeresa Johnson std::unique_ptr<FunctionInfoIndex> IndexPtr; 3665fcbdb71STeresa Johnson if (!SummaryFile.empty()) { 3675fcbdb71STeresa Johnson if (Index) 3685fcbdb71STeresa Johnson report_fatal_error("error: -summary-file and index from frontend\n"); 36942418abaSMehdi Amini std::string Error; 3705fcbdb71STeresa Johnson IndexPtr = getFunctionIndexForFile(SummaryFile, Error, diagnosticHandler); 3715fcbdb71STeresa Johnson if (!IndexPtr) { 3725fcbdb71STeresa Johnson errs() << "Error loading file '" << SummaryFile << "': " << Error 3735fcbdb71STeresa Johnson << "\n"; 37442418abaSMehdi Amini return false; 37542418abaSMehdi Amini } 3765fcbdb71STeresa Johnson Index = IndexPtr.get(); 3775fcbdb71STeresa Johnson } 37842418abaSMehdi Amini 37942418abaSMehdi Amini // Perform the import now. 380d16c8065SMehdi Amini auto ModuleLoader = [&M](StringRef Identifier) { 381d16c8065SMehdi Amini return loadFile(Identifier, M.getContext()); 382d16c8065SMehdi Amini }; 383*9d2bfc48SRafael Espindola FunctionImporter Importer(*Index, ModuleLoader); 38442418abaSMehdi Amini return Importer.importFunctions(M); 38542418abaSMehdi Amini 38642418abaSMehdi Amini return false; 38742418abaSMehdi Amini } 38842418abaSMehdi Amini }; 38942418abaSMehdi Amini 39042418abaSMehdi Amini char FunctionImportPass::ID = 0; 39142418abaSMehdi Amini INITIALIZE_PASS_BEGIN(FunctionImportPass, "function-import", 39242418abaSMehdi Amini "Summary Based Function Import", false, false) 39342418abaSMehdi Amini INITIALIZE_PASS_END(FunctionImportPass, "function-import", 39442418abaSMehdi Amini "Summary Based Function Import", false, false) 39542418abaSMehdi Amini 39642418abaSMehdi Amini namespace llvm { 3977f961e14STeresa Johnson Pass *createFunctionImportPass(const FunctionInfoIndex *Index = nullptr) { 3985fcbdb71STeresa Johnson return new FunctionImportPass(Index); 3995fcbdb71STeresa Johnson } 40042418abaSMehdi Amini } 401