mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-12 14:20:33 +00:00
eba0415600
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47900 91177308-0d34-0410-b5e6-96231b3b80d8
207 lines
7.4 KiB
C++
207 lines
7.4 KiB
C++
//===- lib/Linker/LinkArchives.cpp - Link LLVM objects and libraries ------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// This file contains routines to handle linking together LLVM bitcode files,
|
|
// and to handle annoying things like static libraries.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/Linker.h"
|
|
#include "llvm/Module.h"
|
|
#include "llvm/ModuleProvider.h"
|
|
#include "llvm/ADT/SetOperations.h"
|
|
#include "llvm/Bitcode/Archive.h"
|
|
#include "llvm/Config/config.h"
|
|
#include <memory>
|
|
#include <set>
|
|
using namespace llvm;
|
|
|
|
/// GetAllUndefinedSymbols - calculates the set of undefined symbols that still
|
|
/// exist in an LLVM module. This is a bit tricky because there may be two
|
|
/// symbols with the same name but different LLVM types that will be resolved to
|
|
/// each other but aren't currently (thus we need to treat it as resolved).
|
|
///
|
|
/// Inputs:
|
|
/// M - The module in which to find undefined symbols.
|
|
///
|
|
/// Outputs:
|
|
/// UndefinedSymbols - A set of C++ strings containing the name of all
|
|
/// undefined symbols.
|
|
///
|
|
static void
|
|
GetAllUndefinedSymbols(Module *M, std::set<std::string> &UndefinedSymbols) {
|
|
std::set<std::string> DefinedSymbols;
|
|
UndefinedSymbols.clear();
|
|
|
|
// If the program doesn't define a main, try pulling one in from a .a file.
|
|
// This is needed for programs where the main function is defined in an
|
|
// archive, such f2c'd programs.
|
|
Function *Main = M->getFunction("main");
|
|
if (Main == 0 || Main->isDeclaration())
|
|
UndefinedSymbols.insert("main");
|
|
|
|
for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
|
|
if (I->hasName()) {
|
|
if (I->isDeclaration())
|
|
UndefinedSymbols.insert(I->getName());
|
|
else if (!I->hasInternalLinkage()) {
|
|
assert(!I->hasDLLImportLinkage()
|
|
&& "Found dllimported non-external symbol!");
|
|
DefinedSymbols.insert(I->getName());
|
|
}
|
|
}
|
|
|
|
for (Module::global_iterator I = M->global_begin(), E = M->global_end();
|
|
I != E; ++I)
|
|
if (I->hasName()) {
|
|
if (I->isDeclaration())
|
|
UndefinedSymbols.insert(I->getName());
|
|
else if (!I->hasInternalLinkage()) {
|
|
assert(!I->hasDLLImportLinkage()
|
|
&& "Found dllimported non-external symbol!");
|
|
DefinedSymbols.insert(I->getName());
|
|
}
|
|
}
|
|
|
|
for (Module::alias_iterator I = M->alias_begin(), E = M->alias_end();
|
|
I != E; ++I)
|
|
if (I->hasName()) {
|
|
const GlobalValue *Aliased = I->getAliasedGlobal();
|
|
if (Aliased->isDeclaration())
|
|
UndefinedSymbols.insert(I->getName());
|
|
else
|
|
DefinedSymbols.insert(I->getName());
|
|
}
|
|
|
|
// Prune out any defined symbols from the undefined symbols set...
|
|
for (std::set<std::string>::iterator I = UndefinedSymbols.begin();
|
|
I != UndefinedSymbols.end(); )
|
|
if (DefinedSymbols.count(*I))
|
|
UndefinedSymbols.erase(I++); // This symbol really is defined!
|
|
else
|
|
++I; // Keep this symbol in the undefined symbols list
|
|
}
|
|
|
|
/// LinkInArchive - opens an archive library and link in all objects which
|
|
/// provide symbols that are currently undefined.
|
|
///
|
|
/// Inputs:
|
|
/// Filename - The pathname of the archive.
|
|
///
|
|
/// Return Value:
|
|
/// TRUE - An error occurred.
|
|
/// FALSE - No errors.
|
|
bool
|
|
Linker::LinkInArchive(const sys::Path &Filename, bool &is_native) {
|
|
// Make sure this is an archive file we're dealing with
|
|
if (!Filename.isArchive())
|
|
return error("File '" + Filename.toString() + "' is not an archive.");
|
|
|
|
// Open the archive file
|
|
verbose("Linking archive file '" + Filename.toString() + "'");
|
|
|
|
// Find all of the symbols currently undefined in the bitcode program.
|
|
// If all the symbols are defined, the program is complete, and there is
|
|
// no reason to link in any archive files.
|
|
std::set<std::string> UndefinedSymbols;
|
|
GetAllUndefinedSymbols(Composite, UndefinedSymbols);
|
|
|
|
if (UndefinedSymbols.empty()) {
|
|
verbose("No symbols undefined, skipping library '" +
|
|
Filename.toString() + "'");
|
|
return false; // No need to link anything in!
|
|
}
|
|
|
|
std::string ErrMsg;
|
|
std::auto_ptr<Archive> AutoArch (
|
|
Archive::OpenAndLoadSymbols(Filename,&ErrMsg));
|
|
|
|
Archive* arch = AutoArch.get();
|
|
|
|
if (!arch)
|
|
return error("Cannot read archive '" + Filename.toString() +
|
|
"': " + ErrMsg);
|
|
if (!arch->isBitcodeArchive()) {
|
|
is_native = true;
|
|
return false;
|
|
}
|
|
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
|
|
std::set<ModuleProvider*> Modules;
|
|
if (!arch->findModulesDefiningSymbols(UndefinedSymbols, Modules, &ErrMsg))
|
|
return error("Cannot find symbols in '" + Filename.toString() +
|
|
"': " + 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 ModuleProviders that we got back from the archive
|
|
for (std::set<ModuleProvider*>::iterator I=Modules.begin(), E=Modules.end();
|
|
I != E; ++I) {
|
|
|
|
// Get the module we must link in.
|
|
std::string moduleErrorMsg;
|
|
std::auto_ptr<Module> AutoModule((*I)->releaseModule( &moduleErrorMsg ));
|
|
if (!moduleErrorMsg.empty())
|
|
return error("Could not load a module: " + moduleErrorMsg);
|
|
|
|
Module* aModule = AutoModule.get();
|
|
|
|
if (aModule != NULL) {
|
|
verbose(" Linking in module: " + aModule->getModuleIdentifier());
|
|
|
|
// Link it in
|
|
if (LinkInModule(aModule, &moduleErrorMsg)) {
|
|
return error("Cannot link in module '" +
|
|
aModule->getModuleIdentifier() + "': " + moduleErrorMsg);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Get the undefined symbols from the aggregate module. This recomputes the
|
|
// symbols we still need after the new modules have been linked in.
|
|
GetAllUndefinedSymbols(Composite, UndefinedSymbols);
|
|
|
|
// At this point we have two sets of undefined symbols: UndefinedSymbols
|
|
// which holds the undefined symbols from all the modules, and
|
|
// NotDefinedByArchive which holds symbols we know the archive doesn't
|
|
// define. There's no point searching for symbols that we won't find in the
|
|
// archive so we subtract these sets.
|
|
set_subtract(UndefinedSymbols, NotDefinedByArchive);
|
|
|
|
// If there's no symbols left, no point in continuing to search the
|
|
// archive.
|
|
if (UndefinedSymbols.empty())
|
|
break;
|
|
} while (CurrentlyUndefinedSymbols != UndefinedSymbols);
|
|
|
|
return false;
|
|
}
|