Files
lld/ELF/LTO.cpp
Peter Smith 1a0ca791ab [ELF][ARM] Use SyntheticSections for Thunks
Thunks are now implemented by redirecting the relocation to the
symbol S, to a symbol TS in a Thunk. The Thunk will transfer control
to S. This has the following implications:
- All the side-effects of Thunks happen within createThunks()
- Thunks are no longer stored in InputSections and Symbols no longer
  need to hold a pointer to a Thunk
- The synthetic Thunk sections need to be merged into OutputSections
    
This implementation is almost a direct conversion of the existing
Thunks with the following exceptions:
- Mips LA25 Thunks are placed before the InputSection that defines
  the symbol that needs a Thunk.
- All ARM Thunks are placed at the end of the OutputSection of the
  first caller to the Thunk.
    
Range extension Thunks are not supported yet so it is optimistically
assumed that all Thunks can be reused.

Differential Revision:  https://reviews.llvm.org/D29129



git-svn-id: https://llvm.org/svn/llvm-project/lld/trunk@293283 91177308-0d34-0410-b5e6-96231b3b80d8
2017-01-27 13:10:16 +00:00

160 lines
4.9 KiB
C++

//===- LTO.cpp ------------------------------------------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "LTO.h"
#include "Config.h"
#include "Error.h"
#include "InputFiles.h"
#include "Symbols.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/CodeGen/CommandFlags.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/LTO/Config.h"
#include "llvm/LTO/LTO.h"
#include "llvm/Object/SymbolicFile.h"
#include "llvm/Support/CodeGen.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstddef>
#include <memory>
#include <string>
#include <system_error>
#include <vector>
using namespace llvm;
using namespace llvm::object;
using namespace llvm::ELF;
using namespace lld;
using namespace lld::elf;
// This is for use when debugging LTO.
static void saveBuffer(StringRef Buffer, const Twine &Path) {
std::error_code EC;
raw_fd_ostream OS(Path.str(), EC, sys::fs::OpenFlags::F_None);
if (EC)
error("cannot create " + Path + ": " + EC.message());
OS << Buffer;
}
static void diagnosticHandler(const DiagnosticInfo &DI) {
SmallString<128> ErrStorage;
raw_svector_ostream OS(ErrStorage);
DiagnosticPrinterRawOStream DP(OS);
DI.print(DP);
warn(ErrStorage);
}
static void checkError(Error E) {
handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) -> Error {
error(EIB.message());
return Error::success();
});
}
static std::unique_ptr<lto::LTO> createLTO() {
lto::Config Conf;
// LLD supports the new relocations.
Conf.Options = InitTargetOptionsFromCodeGenFlags();
Conf.Options.RelaxELFRelocations = true;
Conf.RelocModel = Config->Pic ? Reloc::PIC_ : Reloc::Static;
Conf.DisableVerify = Config->DisableVerify;
Conf.DiagHandler = diagnosticHandler;
Conf.OptLevel = Config->LTOO;
// Set up a custom pipeline if we've been asked to.
Conf.OptPipeline = Config->LTONewPmPasses;
Conf.AAPipeline = Config->LTOAAPipeline;
if (Config->SaveTemps)
checkError(Conf.addSaveTemps(std::string(Config->OutputFile) + ".",
/*UseInputModulePath*/ true));
lto::ThinBackend Backend;
if (Config->ThinLTOJobs != -1u)
Backend = lto::createInProcessThinBackend(Config->ThinLTOJobs);
return llvm::make_unique<lto::LTO>(std::move(Conf), Backend,
Config->LTOPartitions);
}
BitcodeCompiler::BitcodeCompiler() : LTOObj(createLTO()) {}
BitcodeCompiler::~BitcodeCompiler() = default;
static void undefine(Symbol *S) {
replaceBody<Undefined>(S, S->body()->getName(), /*IsLocal=*/false,
STV_DEFAULT, S->body()->Type, nullptr);
}
void BitcodeCompiler::add(BitcodeFile &F) {
lto::InputFile &Obj = *F.Obj;
unsigned SymNum = 0;
std::vector<Symbol *> Syms = F.getSymbols();
std::vector<lto::SymbolResolution> Resols(Syms.size());
// Provide a resolution to the LTO API for each symbol.
for (const lto::InputFile::Symbol &ObjSym : Obj.symbols()) {
Symbol *Sym = Syms[SymNum];
lto::SymbolResolution &R = Resols[SymNum];
++SymNum;
SymbolBody *B = Sym->body();
// Ideally we shouldn't check for SF_Undefined but currently IRObjectFile
// reports two symbols for module ASM defined. Without this check, lld
// flags an undefined in IR with a definition in ASM as prevailing.
// Once IRObjectFile is fixed to report only one symbol this hack can
// be removed.
R.Prevailing =
!(ObjSym.getFlags() & object::BasicSymbolRef::SF_Undefined) &&
B->File == &F;
R.VisibleToRegularObj =
Sym->IsUsedInRegularObj || (R.Prevailing && Sym->includeInDynsym());
if (R.Prevailing)
undefine(Sym);
}
checkError(LTOObj->add(std::move(F.Obj), Resols));
}
// Merge all the bitcode files we have seen, codegen the result
// and return the resulting ObjectFile(s).
std::vector<InputFile *> BitcodeCompiler::compile() {
std::vector<InputFile *> Ret;
unsigned MaxTasks = LTOObj->getMaxTasks();
Buff.resize(MaxTasks);
checkError(LTOObj->run([&](size_t Task) {
return llvm::make_unique<lto::NativeObjectStream>(
llvm::make_unique<raw_svector_ostream>(Buff[Task]));
}));
for (unsigned I = 0; I != MaxTasks; ++I) {
if (Buff[I].empty())
continue;
if (Config->SaveTemps) {
if (I == 0)
saveBuffer(Buff[I], Config->OutputFile + ".lto.o");
else
saveBuffer(Buff[I], Config->OutputFile + Twine(I) + ".lto.o");
}
InputFile *Obj = createObjectFile(MemoryBufferRef(Buff[I], "lto.tmp"));
Ret.push_back(Obj);
}
return Ret;
}