Previously, all input files were owned by the symbol table.
Files were created at various places, such as the Driver, the lazy
symbols, or the bitcode compiler, and the ownership of new files
was transferred to the symbol table using std::unique_ptr.
All input files were then free'd when the symbol table is freed
which is on program exit.
I think we don't have to transfer ownership just to free all
instance at once on exit.
In this patch, all instances are automatically collected to a
vector and freed on exit. In this way, we no longer have to
use std::unique_ptr.
Differential Revision: https://reviews.llvm.org/D24493
llvm-svn: 281425
ScriptConfig = ≻
Driver->main(Args);
+ InputFile::freePool();
return !HasError;
}
MemoryBufferRef MBRef = *Buffer;
if (Config->Binary && !KnownScript) {
- Files.push_back(make_unique<BinaryFile>(MBRef));
+ Files.push_back(new BinaryFile(MBRef));
return;
}
Files.push_back(createObjectFile(MB, Path));
return;
}
- Files.push_back(make_unique<ArchiveFile>(MBRef));
+ Files.push_back(new ArchiveFile(MBRef));
return;
case file_magic::elf_shared_object:
if (Config->Relocatable) {
return;
default:
if (InLib)
- Files.push_back(make_unique<LazyObjectFile>(MBRef));
+ Files.push_back(new LazyObjectFile(MBRef));
else
Files.push_back(createObjectFile(MBRef));
}
// If -m <machine_type> was not given, infer it from object files.
if (Config->EKind == ELFNoneKind) {
- for (std::unique_ptr<InputFile> &F : Files) {
+ for (InputFile *F : Files) {
if (F->EKind == ELFNoneKind)
continue;
Config->EKind = F->EKind;
// Add all files to the symbol table. After this, the symbol table
// contains all known names except a few linker-synthesized symbols.
- for (std::unique_ptr<InputFile> &F : Files)
- Symtab.addFile(std::move(F));
+ for (InputFile *F : Files)
+ Symtab.addFile(F);
// Add the start symbol.
// It initializes either Config->Entry or Config->EntryAddr.
// MergeInputSection::splitIntoPieces needs to be called before
// any call of MergeInputSection::getOffset. Do that.
- for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F :
- Symtab.getObjectFiles())
+ for (elf::ObjectFile<ELFT> *F : Symtab.getObjectFiles()) {
for (InputSectionBase<ELFT> *S : F->getSections()) {
if (!S || S == &InputSection<ELFT>::Discarded || !S->Live)
continue;
if (auto *MS = dyn_cast<MergeInputSection<ELFT>>(S))
MS->splitIntoPieces();
}
+ }
// Write the result to the file.
writeResult<ELFT>();
bool InLib = false;
llvm::BumpPtrAllocator Alloc;
- std::vector<std::unique_ptr<InputFile>> Files;
+ std::vector<InputFile *> Files;
std::vector<std::unique_ptr<MemoryBuffer>> OwningMBs;
};
template <class ELFT>
std::vector<InputSection<ELFT> *> ICF<ELFT>::getSections() {
std::vector<InputSection<ELFT> *> V;
- for (const std::unique_ptr<ObjectFile<ELFT>> &F :
- Symtab<ELFT>::X->getObjectFiles())
+ for (ObjectFile<ELFT> *F : Symtab<ELFT>::X->getObjectFiles())
for (InputSectionBase<ELFT> *S : F->getSections())
if (isEligible(S))
V.push_back(cast<InputSection<ELFT>>(S));
using namespace lld;
using namespace lld::elf;
+std::vector<InputFile *> InputFile::Pool;
+
+// Deletes all InputFile instances created so far.
+void InputFile::freePool() {
+ // Files are freed in reverse order so that files created
+ // from other files (e.g. object files extracted from archives)
+ // are freed in the proper order.
+ for (int I = Pool.size() - 1; I >= 0; --I)
+ delete Pool[I];
+}
+
// Returns "(internal)", "foo.a(bar.o)" or "baz.o".
std::string elf::getFilename(const InputFile *F) {
if (!F)
}
template <template <class> class T>
-static std::unique_ptr<InputFile> createELFFile(MemoryBufferRef MB) {
+static InputFile *createELFFile(MemoryBufferRef MB) {
unsigned char Size;
unsigned char Endian;
std::tie(Size, Endian) = getElfArchType(MB.getBuffer());
if (Endian != ELFDATA2LSB && Endian != ELFDATA2MSB)
fatal("invalid data encoding: " + MB.getBufferIdentifier());
- std::unique_ptr<InputFile> Obj;
+ InputFile *Obj;
if (Size == ELFCLASS32 && Endian == ELFDATA2LSB)
- Obj.reset(new T<ELF32LE>(MB));
+ Obj = new T<ELF32LE>(MB);
else if (Size == ELFCLASS32 && Endian == ELFDATA2MSB)
- Obj.reset(new T<ELF32BE>(MB));
+ Obj = new T<ELF32BE>(MB);
else if (Size == ELFCLASS64 && Endian == ELFDATA2LSB)
- Obj.reset(new T<ELF64LE>(MB));
+ Obj = new T<ELF64LE>(MB);
else if (Size == ELFCLASS64 && Endian == ELFDATA2MSB)
- Obj.reset(new T<ELF64BE>(MB));
+ Obj = new T<ELF64BE>(MB);
else
fatal("invalid file class: " + MB.getBufferIdentifier());
if (!Config->FirstElf)
- Config->FirstElf = Obj.get();
+ Config->FirstElf = Obj;
return Obj;
}
-template <class ELFT> std::unique_ptr<InputFile> BinaryFile::createELF() {
+template <class ELFT> InputFile *BinaryFile::createELF() {
// Wrap the binary blob with an ELF header and footer
// so that we can link it as a regular ELF file.
ELFCreator<ELFT> ELF(ET_REL, Config->EMachine);
return identify_magic(MB.getBuffer()) == file_magic::bitcode;
}
-std::unique_ptr<InputFile> elf::createObjectFile(MemoryBufferRef MB,
- StringRef ArchiveName) {
- std::unique_ptr<InputFile> F;
- if (isBitcode(MB))
- F.reset(new BitcodeFile(MB));
- else
- F = createELFFile<ObjectFile>(MB);
+InputFile *elf::createObjectFile(MemoryBufferRef MB, StringRef ArchiveName) {
+ InputFile *F =
+ isBitcode(MB) ? new BitcodeFile(MB) : createELFFile<ObjectFile>(MB);
F->ArchiveName = ArchiveName;
return F;
}
-std::unique_ptr<InputFile> elf::createSharedFile(MemoryBufferRef MB) {
+InputFile *elf::createSharedFile(MemoryBufferRef MB) {
return createELFFile<SharedFile>(MB);
}
template class elf::SharedFile<ELF64LE>;
template class elf::SharedFile<ELF64BE>;
-template std::unique_ptr<InputFile> BinaryFile::createELF<ELF32LE>();
-template std::unique_ptr<InputFile> BinaryFile::createELF<ELF32BE>();
-template std::unique_ptr<InputFile> BinaryFile::createELF<ELF64LE>();
-template std::unique_ptr<InputFile> BinaryFile::createELF<ELF64BE>();
+template InputFile *BinaryFile::createELF<ELF32LE>();
+template InputFile *BinaryFile::createELF<ELF32BE>();
+template InputFile *BinaryFile::createELF<ELF64LE>();
+template InputFile *BinaryFile::createELF<ELF64BE>();
// The root class of input files.
class InputFile {
public:
+ virtual ~InputFile() = default;
+
enum Kind {
ObjectKind,
SharedKind,
ELFKind EKind = ELFNoneKind;
uint16_t EMachine = llvm::ELF::EM_NONE;
+ static void freePool();
+
protected:
- InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {}
+ InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {
+ Pool.push_back(this);
+ }
private:
const Kind FileKind;
+
+ // All InputFile instances are added to the pool
+ // and freed all at once on exit by freePool().
+ static std::vector<InputFile *> Pool;
};
// Returns "(internal)", "foo.a(bar.o)" or "baz.o".
static bool classof(const InputFile *F) { return F->kind() == BinaryKind; }
- template <class ELFT> std::unique_ptr<InputFile> createELF();
+ template <class ELFT> InputFile *createELF();
private:
std::vector<uint8_t> ELFData;
};
-std::unique_ptr<InputFile> createObjectFile(MemoryBufferRef MB,
- StringRef ArchiveName = "");
-std::unique_ptr<InputFile> createSharedFile(MemoryBufferRef MB);
+InputFile *createObjectFile(MemoryBufferRef MB, StringRef ArchiveName = "");
+InputFile *createSharedFile(MemoryBufferRef MB);
} // namespace elf
} // namespace lld
GV.setLinkage(GlobalValue::InternalLinkage);
}
-std::vector<std::unique_ptr<InputFile>> BitcodeCompiler::runSplitCodegen(
+std::vector<InputFile *> BitcodeCompiler::runSplitCodegen(
const std::function<std::unique_ptr<TargetMachine>()> &TMFactory) {
unsigned NumThreads = Config->LtoJobs;
OwningData.resize(NumThreads);
splitCodeGen(std::move(Combined), OSPtrs, {}, TMFactory);
- std::vector<std::unique_ptr<InputFile>> ObjFiles;
+ std::vector<InputFile *> ObjFiles;
for (SmallString<0> &Obj : OwningData)
ObjFiles.push_back(createObjectFile(
MemoryBufferRef(Obj, "LLD-INTERNAL-combined-lto-object")));
// Merge all the bitcode files we have seen, codegen the result
// and return the resulting ObjectFile.
-std::vector<std::unique_ptr<InputFile>> BitcodeCompiler::compile() {
+std::vector<InputFile *> BitcodeCompiler::compile() {
for (const auto &Name : InternalizedSyms) {
GlobalValue *GV = Combined->getNamedValue(Name.first());
assert(GV);
public:
BitcodeCompiler();
void add(BitcodeFile &F);
- std::vector<std::unique_ptr<InputFile>> compile();
+ std::vector<InputFile *> compile();
private:
- std::vector<std::unique_ptr<InputFile>> runSplitCodegen(
+ std::vector<InputFile *> runSplitCodegen(
const std::function<std::unique_ptr<llvm::TargetMachine>()> &TMFactory);
std::unique_ptr<llvm::Module> Combined;
LinkerScript<ELFT>::getInputSections(const InputSectionDescription *I) {
const Regex &Re = I->SectionRe;
std::vector<InputSectionBase<ELFT> *> Ret;
- for (const std::unique_ptr<ObjectFile<ELFT>> &F :
- Symtab<ELFT>::X->getObjectFiles()) {
+ for (ObjectFile<ELFT> *F : Symtab<ELFT>::X->getObjectFiles())
if (fileMatches(I, sys::path::filename(F->getName())))
for (InputSectionBase<ELFT> *S : F->getSections())
if (!isDiscarded(S) && !S->OutSec &&
const_cast<Regex &>(Re).match(S->Name))
Ret.push_back(S);
- }
if (const_cast<Regex &>(Re).match("COMMON"))
Ret.push_back(CommonInputSection<ELFT>::X);
}
// Add orphan sections.
- for (const std::unique_ptr<ObjectFile<ELFT>> &F :
- Symtab<ELFT>::X->getObjectFiles()) {
+ for (ObjectFile<ELFT> *F : Symtab<ELFT>::X->getObjectFiles()) {
for (InputSectionBase<ELFT> *S : F->getSections()) {
if (isDiscarded(S) || S->OutSec)
continue;
// Preserve special sections and those which are specified in linker
// script KEEP command.
- for (const std::unique_ptr<ObjectFile<ELFT>> &F :
- Symtab<ELFT>::X->getObjectFiles())
- for (InputSectionBase<ELFT> *Sec : F->getSections())
+ for (ObjectFile<ELFT> *F : Symtab<ELFT>::X->getObjectFiles()) {
+ for (InputSectionBase<ELFT> *Sec : F->getSections()) {
if (Sec && Sec != &InputSection<ELFT>::Discarded) {
// .eh_frame is always marked as live now, but also it can reference to
// sections that contain personality. We preserve all non-text sections
if (isReserved(Sec) || Script<ELFT>::X->shouldKeep(Sec))
Enqueue({Sec, 0});
}
+ }
+ }
// Mark all reachable sections.
while (!Q.empty())
template <class ELFT> uint32_t elf::getMipsEFlags() {
std::vector<FileFlags> V;
- for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F :
- Symtab<ELFT>::X->getObjectFiles())
+ for (elf::ObjectFile<ELFT> *F : Symtab<ELFT>::X->getObjectFiles())
V.push_back({F->getName(), F->getObj().getHeader()->e_flags});
-
checkFlags(V);
return getMiscFlags(V) | getPicFlags(V) | getArchFlags(V);
}
if (!Config->RPath.empty())
Add({Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH,
Out<ELFT>::DynStrTab->addString(Config->RPath)});
- for (const std::unique_ptr<SharedFile<ELFT>> &F :
- Symtab<ELFT>::X->getSharedFiles())
+ for (SharedFile<ELFT> *F : Symtab<ELFT>::X->getSharedFiles())
if (F->isNeeded())
Add({DT_NEEDED, Out<ELFT>::DynStrTab->addString(F->getSoName())});
if (!Config->SoName.empty())
void SymbolTableSection<ELFT>::writeLocalSymbols(uint8_t *&Buf) {
// Iterate over all input object files to copy their local symbols
// to the output symbol table pointed by Buf.
- for (const std::unique_ptr<ObjectFile<ELFT>> &File :
- Symtab<ELFT>::X->getObjectFiles()) {
+ for (ObjectFile<ELFT> *File : Symtab<ELFT>::X->getObjectFiles()) {
for (const std::pair<const DefinedRegular<ELFT> *, size_t> &P :
File->KeptLocalSyms) {
const DefinedRegular<ELFT> &Body = *P.first;
}
// Add symbols in File to the symbol table.
-template <class ELFT>
-void SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) {
- InputFile *FileP = File.get();
- if (!isCompatible<ELFT>(FileP))
+template <class ELFT> void SymbolTable<ELFT>::addFile(InputFile *File) {
+ if (!isCompatible<ELFT>(File))
return;
// Binary file
- if (auto *F = dyn_cast<BinaryFile>(FileP)) {
- BinaryFiles.emplace_back(cast<BinaryFile>(File.release()));
+ if (auto *F = dyn_cast<BinaryFile>(File)) {
addFile(F->createELF<ELFT>());
return;
}
// .a file
- if (auto *F = dyn_cast<ArchiveFile>(FileP)) {
- ArchiveFiles.emplace_back(cast<ArchiveFile>(File.release()));
+ if (auto *F = dyn_cast<ArchiveFile>(File)) {
F->parse<ELFT>();
return;
}
// Lazy object file
- if (auto *F = dyn_cast<LazyObjectFile>(FileP)) {
- LazyObjectFiles.emplace_back(cast<LazyObjectFile>(File.release()));
+ if (auto *F = dyn_cast<LazyObjectFile>(File)) {
F->parse<ELFT>();
return;
}
if (Config->Trace)
- outs() << getFilename(FileP) << "\n";
+ outs() << getFilename(File) << "\n";
// .so file
- if (auto *F = dyn_cast<SharedFile<ELFT>>(FileP)) {
+ if (auto *F = dyn_cast<SharedFile<ELFT>>(File)) {
// DSOs are uniquified not by filename but by soname.
F->parseSoName();
if (!SoNames.insert(F->getSoName()).second)
return;
-
- SharedFiles.emplace_back(cast<SharedFile<ELFT>>(File.release()));
+ SharedFiles.push_back(F);
F->parseRest();
return;
}
// LLVM bitcode file
- if (auto *F = dyn_cast<BitcodeFile>(FileP)) {
- BitcodeFiles.emplace_back(cast<BitcodeFile>(File.release()));
+ if (auto *F = dyn_cast<BitcodeFile>(File)) {
+ BitcodeFiles.push_back(F);
F->parse<ELFT>(ComdatGroups);
return;
}
// Regular object file
- auto *F = cast<ObjectFile<ELFT>>(FileP);
- ObjectFiles.emplace_back(cast<ObjectFile<ELFT>>(File.release()));
+ auto *F = cast<ObjectFile<ELFT>>(File);
+ ObjectFiles.push_back(F);
F->parse(ComdatGroups);
}
if (BitcodeFiles.empty())
return;
- // Compile bitcode files.
+ // Compile bitcode files and replace bitcode symbols.
Lto.reset(new BitcodeCompiler);
- for (const std::unique_ptr<BitcodeFile> &F : BitcodeFiles)
+ for (BitcodeFile *F : BitcodeFiles)
Lto->add(*F);
- std::vector<std::unique_ptr<InputFile>> IFs = Lto->compile();
-
- // Replace bitcode symbols.
- for (auto &IF : IFs) {
- ObjectFile<ELFT> *Obj = cast<ObjectFile<ELFT>>(IF.release());
+ for (InputFile *File : Lto->compile()) {
+ ObjectFile<ELFT> *Obj = cast<ObjectFile<ELFT>>(File);
DenseSet<StringRef> DummyGroups;
Obj->parse(DummyGroups);
- ObjectFiles.emplace_back(Obj);
+ ObjectFiles.push_back(Obj);
}
}
// its type. See also comment in addLazyArchive.
if (S->isWeak())
L->Type = Type;
- else if (auto F = L->fetch())
- addFile(std::move(F));
+ else if (InputFile *F = L->fetch())
+ addFile(F);
}
return S;
}
template <class ELFT> void SymbolTable<ELFT>::scanUndefinedFlags() {
for (StringRef S : Config->Undefined)
if (auto *L = dyn_cast_or_null<Lazy>(find(S)))
- if (std::unique_ptr<InputFile> File = L->fetch())
- addFile(std::move(File));
+ if (InputFile *File = L->fetch())
+ addFile(File);
}
// This function takes care of the case in which shared libraries depend on
// shared libraries can find them.
// Except this, we ignore undefined symbols in DSOs.
template <class ELFT> void SymbolTable<ELFT>::scanShlibUndefined() {
- for (std::unique_ptr<SharedFile<ELFT>> &File : SharedFiles)
+ for (SharedFile<ELFT> *File : SharedFiles)
for (StringRef U : File->getUndefinedSymbols())
if (SymbolBody *Sym = find(U))
if (Sym->isDefined())
typedef typename ELFT::uint uintX_t;
public:
- void addFile(std::unique_ptr<InputFile> File);
+ void addFile(InputFile *File);
void addCombinedLtoObject();
llvm::ArrayRef<Symbol *> getSymbols() const { return SymVector; }
- const std::vector<std::unique_ptr<ObjectFile<ELFT>>> &getObjectFiles() const {
+ const std::vector<ObjectFile<ELFT> *> &getObjectFiles() const {
return ObjectFiles;
}
- const std::vector<std::unique_ptr<SharedFile<ELFT>>> &getSharedFiles() const {
+ const std::vector<SharedFile<ELFT> *> &getSharedFiles() const {
return SharedFiles;
}
// is used to uniquify them.
llvm::DenseSet<StringRef> ComdatGroups;
- // The symbol table owns all file objects.
- std::vector<std::unique_ptr<ArchiveFile>> ArchiveFiles;
- std::vector<std::unique_ptr<BinaryFile>> BinaryFiles;
- std::vector<std::unique_ptr<ObjectFile<ELFT>>> ObjectFiles;
- std::vector<std::unique_ptr<LazyObjectFile>> LazyObjectFiles;
- std::vector<std::unique_ptr<SharedFile<ELFT>>> SharedFiles;
- std::vector<std::unique_ptr<BitcodeFile>> BitcodeFiles;
+ std::vector<ObjectFile<ELFT> *> ObjectFiles;
+ std::vector<SharedFile<ELFT> *> SharedFiles;
+ std::vector<BitcodeFile *> BitcodeFiles;
// Set of .so files to not link the same shared object file more than once.
llvm::DenseSet<StringRef> SoNames;
this->File = File;
}
-std::unique_ptr<InputFile> Lazy::fetch() {
+InputFile *Lazy::fetch() {
if (auto *S = dyn_cast<LazyArchive>(this))
return S->fetch();
return cast<LazyObject>(this)->fetch();
this->File = &File;
}
-std::unique_ptr<InputFile> LazyArchive::fetch() {
+InputFile *LazyArchive::fetch() {
MemoryBufferRef MBRef = file()->getMember(&Sym);
// getMember returns an empty buffer if the member was already
// read from the library.
if (MBRef.getBuffer().empty())
- return std::unique_ptr<InputFile>(nullptr);
+ return nullptr;
return createObjectFile(MBRef, file()->getName());
}
-std::unique_ptr<InputFile> LazyObject::fetch() {
+InputFile *LazyObject::fetch() {
MemoryBufferRef MBRef = file()->getBuffer();
if (MBRef.getBuffer().empty())
- return std::unique_ptr<InputFile>(nullptr);
+ return nullptr;
return createObjectFile(MBRef);
}
// Returns an object file for this symbol, or a nullptr if the file
// was already returned.
- std::unique_ptr<InputFile> fetch();
+ InputFile *fetch();
protected:
Lazy(SymbolBody::Kind K, StringRef Name, uint8_t Type)
}
ArchiveFile *file() { return (ArchiveFile *)this->File; }
- std::unique_ptr<InputFile> fetch();
+ InputFile *fetch();
private:
const llvm::object::Archive::Symbol Sym;
}
LazyObjectFile *file() { return (LazyObjectFile *)this->File; }
- std::unique_ptr<InputFile> fetch();
+ InputFile *fetch();
};
// Some linker-generated symbols need to be created as
template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
if (!Out<ELFT>::SymTab)
return;
- for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F :
- Symtab<ELFT>::X->getObjectFiles()) {
+ for (elf::ObjectFile<ELFT> *F : Symtab<ELFT>::X->getObjectFiles()) {
const char *StrTab = F->getStringTable().data();
for (SymbolBody *B : F->getLocalSymbols()) {
auto *DR = dyn_cast<DefinedRegular<ELFT>>(B);
void Writer<ELFT>::forEachRelSec(
std::function<void(InputSectionBase<ELFT> &, const typename ELFT::Shdr &)>
Fn) {
- for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F :
- Symtab<ELFT>::X->getObjectFiles()) {
+ for (elf::ObjectFile<ELFT> *F : Symtab<ELFT>::X->getObjectFiles()) {
for (InputSectionBase<ELFT> *C : F->getSections()) {
if (isDiscarded(C))
continue;
}
template <class ELFT> void Writer<ELFT>::createSections() {
- for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F :
- Symtab<ELFT>::X->getObjectFiles()) {
+ for (elf::ObjectFile<ELFT> *F : Symtab<ELFT>::X->getObjectFiles()) {
for (InputSectionBase<ELFT> *C : F->getSections()) {
if (isDiscarded(C)) {
reportDiscarded(C);