-
- return false;
-}
-
-/// LinkInFile - opens an archive library and link in all objects which
-/// provide symbols that are currently undefined.
-///
-/// Inputs:
-/// HeadModule - The module in which to link the archives.
-/// Filename - The pathname of the archive.
-/// Verbose - Flags whether verbose messages should be printed.
-///
-/// Outputs:
-/// ErrorMessage - A C++ string detailing what error occurred, if any.
-///
-/// Return Value:
-/// TRUE - An error occurred.
-/// FALSE - No errors.
-///
-static bool LinkInFile(Module *HeadModule,
- const std::string &Filename,
- std::string &ErrorMessage,
- bool Verbose)
-{
- std::auto_ptr<Module> M(LoadObject(Filename, ErrorMessage));
- if (M.get() == 0) return true;
- if (Verbose) std::cerr << "Linking in '" << Filename << "'\n";
- return LinkModules(HeadModule, M.get(), &ErrorMessage);
-}
-
-/// LinkFiles - takes a module and a list of files and links them all together.
-/// It locates the file either in the current directory, as its absolute
-/// or relative pathname, or as a file somewhere in LLVM_LIB_SEARCH_PATH.
-///
-/// Inputs:
-/// progname - The name of the program (infamous argv[0]).
-/// HeadModule - The module under which all files will be linked.
-/// Files - A vector of C++ strings indicating the LLVM bytecode filenames
-/// to be linked. The names can refer to a mixture of pure LLVM
-/// bytecode files and archive (ar) formatted files.
-/// Verbose - Flags whether verbose output should be printed while linking.
-///
-/// Outputs:
-/// HeadModule - The module will have the specified LLVM bytecode files linked
-/// in.
-///
-/// Return value:
-/// FALSE - No errors.
-/// TRUE - Some error occurred.
-///
-bool LinkFiles(const char *progname,
- Module *HeadModule,
- const std::vector<std::string> &Files,
- bool Verbose)
-{
- // String in which to receive error messages.
- std::string ErrorMessage;
-
- // Full pathname of the file
- std::string Pathname;
-
- // Get the library search path from the environment
- char *SearchPath = getenv("LLVM_LIB_SEARCH_PATH");
-
- for (unsigned i = 1; i < Files.size(); ++i) {
- // Determine where this file lives.
- if (FileExists(Files[i])) {
- Pathname = Files[i];
- } else {
- if (SearchPath == NULL) {
- std::cerr << progname << ": Cannot find linker input file '"
- << Files[i] << "'\n";
- return true;
- }
-
- Pathname = std::string(SearchPath)+"/"+Files[i];
- if (!FileExists(Pathname)) {
- std::cerr << progname << ": Cannot find linker input file '"
- << Files[i] << "'\n";
- return true;
- }
- }
-
- // A user may specify an ar archive without -l, perhaps because it
- // is not installed as a library. Detect that and link the library.
- if (IsArchive(Pathname)) {
- if (Verbose)
- std::cerr << "Linking archive '" << Files[i] << "'\n";
-
- if (LinkInArchive(HeadModule, Pathname, ErrorMessage, Verbose)) {
- PrintAndReturn(progname, ErrorMessage,
- ": Error linking in '" + Files[i] + "'");
- return true;
- }
- } else {
- if (Verbose)
- std::cerr << "Linking file '" << Files[i] << "'\n";
-
- if (LinkInFile(HeadModule, Pathname, ErrorMessage, Verbose)) {
- PrintAndReturn(progname, ErrorMessage,
- ": Error linking in '" + Files[i] + "'");
- return true;
- }
- }
- }
-
- return false;
-}
-
-/// LinkLibraries - takes the specified library files and links them into the
-/// main bytecode object file.
-///
-/// Inputs:
-/// progname - The name of the program (infamous argv[0]).
-/// HeadModule - The module into which all necessary libraries will be linked.
-/// Libraries - The list of libraries to link into the module.
-/// LibPaths - The list of library paths in which to find libraries.
-/// Verbose - Flags whether verbose messages should be printed.
-/// Native - Flags whether native code is being generated.
-///
-/// Outputs:
-/// HeadModule - The module will have all necessary libraries linked in.
-///
-/// Return value:
-/// FALSE - No error.
-/// TRUE - Error.
-///
-bool LinkLibraries(const char *progname,
- Module *HeadModule,
- const std::vector<std::string> &Libraries,
- const std::vector<std::string> &LibPaths,
- bool Verbose,
- bool Native)
-{
- // String in which to receive error messages.
- std::string ErrorMessage;
-
- for (unsigned i = 1; i < Libraries.size(); ++i) {
- // Determine where this library lives.
- std::string Pathname = FindLib(Libraries[i], LibPaths);
- if (Pathname.empty()) {
- // If the pathname does not exist, then continue to the next one if
- // we're doing a native link and give an error if we're doing a bytecode
- // link.
- if (!Native) {
- PrintAndReturn(progname, "Cannot find " + Libraries[i] + "\n");
- return true;
- }
+ is_native = false;
+
+ // Save a set of symbols that are not defined by the archive. Since we're
+ // entering a loop, there's no point searching for these multiple times. This
+ // variable is used to "set_subtract" from the set of undefined symbols.
+ std::set<std::string> NotDefinedByArchive;
+
+ // Save the current set of undefined symbols, because we may have to make
+ // multiple passes over the archive:
+ std::set<std::string> CurrentlyUndefinedSymbols;
+
+ do {
+ CurrentlyUndefinedSymbols = UndefinedSymbols;
+
+ // Find the modules we need to link into the target module. Note that arch
+ // keeps ownership of these modules and may return the same Module* from a
+ // subsequent call.
+ std::set<Module*> Modules;
+ if (!arch->findModulesDefiningSymbols(UndefinedSymbols, Modules, &ErrMsg))
+ return error("Cannot find symbols in '" + Filename.str() +
+ "': " + ErrMsg);
+
+ // If we didn't find any more modules to link this time, we are done
+ // searching this archive.
+ if (Modules.empty())
+ break;
+
+ // Any symbols remaining in UndefinedSymbols after
+ // findModulesDefiningSymbols are ones that the archive does not define. So
+ // we add them to the NotDefinedByArchive variable now.
+ NotDefinedByArchive.insert(UndefinedSymbols.begin(),
+ UndefinedSymbols.end());
+
+ // Loop over all the Modules that we got back from the archive
+ for (std::set<Module*>::iterator I=Modules.begin(), E=Modules.end();
+ I != E; ++I) {
+
+ // Get the module we must link in.
+ std::string moduleErrorMsg;
+ Module* aModule = *I;
+ if (aModule != NULL) {
+ if (aModule->MaterializeAll(&moduleErrorMsg))
+ return error("Could not load a module: " + moduleErrorMsg);
+
+ verbose(" Linking in module: " + aModule->getModuleIdentifier());
+
+ // Link it in
+ if (LinkInModule(aModule, &moduleErrorMsg))
+ return error("Cannot link in module '" +
+ aModule->getModuleIdentifier() + "': " + moduleErrorMsg);
+ }