Example #1
0
// 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);
  }
}