Previously, a MemoryBuffer of a file was owned by each InputFile object.
This patch makes the Driver own all of them. InputFiles now have only
MemoryBufferRefs. This change simplifies ownership managment
(particularly for ObjectFile -- the object owned a MemoryBuffer only when
it's not created from an archive file, because in that case a parent
archive file owned the entire buffer. Now it owns nothing unconditionally.)
llvm-svn: 238690
llvm_unreachable("internal error");
}
-std::unique_ptr<InputFile> createFile(StringRef Path) {
+// Opens a file. Path has to be resolved already.
+// Newly created memory buffers are owned by this driver.
+ErrorOr<std::unique_ptr<InputFile>> LinkerDriver::createFile(StringRef Path) {
+ auto MBOrErr = MemoryBuffer::getFile(Path);
+ if (auto EC = MBOrErr.getError())
+ return EC;
+ std::unique_ptr<MemoryBuffer> MB = std::move(MBOrErr.get());
+ MemoryBufferRef MBRef = MB->getMemBufferRef();
+ OwningMBs.push_back(std::move(MB)); // take ownership
if (StringRef(Path).endswith_lower(".lib"))
- return llvm::make_unique<ArchiveFile>(Path);
- return llvm::make_unique<ObjectFile>(Path);
+ return std::unique_ptr<InputFile>(new ArchiveFile(MBRef));
+ return std::unique_ptr<InputFile>(new ObjectFile(MBRef));
}
namespace {
return EC;
std::unique_ptr<llvm::opt::InputArgList> Args = std::move(ArgsOrErr.get());
- for (auto *Arg : Args->filtered(OPT_defaultlib))
- if (Optional<StringRef> Path = findLib(Arg->getValue()))
- Res->push_back(llvm::make_unique<ArchiveFile>(*Path));
+ for (auto *Arg : Args->filtered(OPT_defaultlib)) {
+ if (Optional<StringRef> Path = findLib(Arg->getValue())) {
+ auto FileOrErr = createFile(*Path);
+ if (auto EC = FileOrErr.getError())
+ return EC;
+ std::unique_ptr<InputFile> File = std::move(FileOrErr.get());
+ Res->push_back(std::move(File));
+ }
+ }
return std::error_code();
}
// Parse all input files and put all symbols to the symbol table.
// The symbol table will take care of name resolution.
for (StringRef Path : Inputs) {
- if (auto EC = Symtab.addFile(createFile(Path))) {
+ auto FileOrErr = createFile(Path);
+ if (auto EC = FileOrErr.getError()) {
+ llvm::errs() << Path << ": " << EC.message() << "\n";
+ return false;
+ }
+ std::unique_ptr<InputFile> File = std::move(FileOrErr.get());
+ if (auto EC = Symtab.addFile(std::move(File))) {
llvm::errs() << Path << ": " << EC.message() << "\n";
return false;
}
private:
StringAllocator Alloc;
+ // Opens a file. Path has to be resolved already.
+ ErrorOr<std::unique_ptr<InputFile>> createFile(StringRef Path);
+
// Searches a file from search paths.
Optional<StringRef> findFile(StringRef Filename);
Optional<StringRef> findLib(StringRef Filename);
std::vector<StringRef> SearchPaths;
std::set<std::string> VisitedFiles;
+
+ // Driver is the owner of all opened files.
+ // InputFiles have MemoryBufferRefs to them.
+ std::vector<std::unique_ptr<MemoryBuffer>> OwningMBs;
};
ErrorOr<std::unique_ptr<llvm::opt::InputArgList>>
}
std::error_code ArchiveFile::parse() {
- // Get a memory buffer.
- auto MBOrErr = MemoryBuffer::getFile(Filename);
- if (auto EC = MBOrErr.getError())
- return EC;
- MB = std::move(MBOrErr.get());
-
- // Parse a memory buffer as an archive file.
- auto ArchiveOrErr = Archive::create(MB->getMemBufferRef());
+ // Parse a MemoryBufferRef as an archive file.
+ auto ArchiveOrErr = Archive::create(MB);
if (auto EC = ArchiveOrErr.getError())
return EC;
File = std::move(ArchiveOrErr.get());
}
std::error_code ObjectFile::parse() {
- // MBRef is not initialized if this is not an archive member.
- if (MBRef.getBuffer().empty()) {
- auto MBOrErr = MemoryBuffer::getFile(Filename);
- if (auto EC = MBOrErr.getError())
- return EC;
- MB = std::move(MBOrErr.get());
- MBRef = MB->getMemBufferRef();
- }
-
// Parse a memory buffer as a COFF file.
- auto BinOrErr = createBinary(MBRef);
+ auto BinOrErr = createBinary(MB);
if (auto EC = BinOrErr.getError())
return EC;
std::unique_ptr<Binary> Bin = std::move(BinOrErr.get());
Bin.release();
COFFObj.reset(Obj);
} else {
- return make_dynamic_error_code(Twine(Filename) + " is not a COFF file.");
+ return make_dynamic_error_code(getName() + " is not a COFF file.");
}
// Read section and symbol tables.
// Get a COFFSymbolRef object.
auto SymOrErr = COFFObj->getSymbol(I);
if (auto EC = SymOrErr.getError())
- return make_dynamic_error_code(Twine("broken object file: ") + Filename +
+ return make_dynamic_error_code("broken object file: " + getName() +
": " + EC.message());
COFFSymbolRef Sym = SymOrErr.get();
// Get a symbol name.
StringRef SymbolName;
if (auto EC = COFFObj->getSymbolName(Sym, SymbolName))
- return make_dynamic_error_code(Twine("broken object file: ") + Filename +
+ return make_dynamic_error_code("broken object file: " + getName() +
": " + EC.message());
// Skip special symbols.
if (SymbolName == "@comp.id" || SymbolName == "@feat.00")
}
std::error_code ImportFile::parse() {
- const char *Buf = MBRef.getBufferStart();
- const char *End = MBRef.getBufferEnd();
+ const char *Buf = MB.getBufferStart();
+ const char *End = MB.getBufferEnd();
const auto *Hdr = reinterpret_cast<const coff_import_header *>(Buf);
// Check if the total size is valid.
// .lib or .a file.
class ArchiveFile : public InputFile {
public:
- explicit ArchiveFile(StringRef S) : InputFile(ArchiveKind), Filename(S) {}
+ explicit ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind), MB(M) {}
static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; }
std::error_code parse() override;
StringRef getName() override { return Filename; }
private:
std::unique_ptr<Archive> File;
std::string Filename;
- std::unique_ptr<MemoryBuffer> MB;
+ MemoryBufferRef MB;
std::vector<SymbolBody *> SymbolBodies;
std::set<const char *> Seen;
llvm::MallocAllocator Alloc;
// .obj or .o file. This may be a member of an archive file.
class ObjectFile : public InputFile {
public:
- explicit ObjectFile(StringRef S) : InputFile(ObjectKind), Filename(S) {}
- ObjectFile(StringRef S, MemoryBufferRef M)
- : InputFile(ObjectKind), Filename(S), MBRef(M) {}
-
+ explicit ObjectFile(MemoryBufferRef M) : InputFile(ObjectKind), MB(M) {}
static bool classof(const InputFile *F) { return F->kind() == ObjectKind; }
std::error_code parse() override;
- StringRef getName() override { return Filename; }
+ StringRef getName() override { return MB.getBufferIdentifier(); }
std::vector<Chunk *> &getChunks() { return Chunks; }
std::vector<SymbolBody *> &getSymbols() override { return SymbolBodies; }
SymbolBody *createSymbolBody(StringRef Name, COFFSymbolRef Sym,
const void *Aux, bool IsFirst);
- std::string Filename;
std::unique_ptr<COFFObjectFile> COFFObj;
- std::unique_ptr<MemoryBuffer> MB;
- MemoryBufferRef MBRef;
+ MemoryBufferRef MB;
StringRef Directives;
llvm::BumpPtrAllocator Alloc;
// for details about the format.
class ImportFile : public InputFile {
public:
- explicit ImportFile(MemoryBufferRef M) : InputFile(ImportKind), MBRef(M) {}
+ explicit ImportFile(MemoryBufferRef M) : InputFile(ImportKind), MB(M) {}
static bool classof(const InputFile *F) { return F->kind() == ImportKind; }
- StringRef getName() override { return MBRef.getBufferIdentifier(); }
+ StringRef getName() override { return MB.getBufferIdentifier(); }
std::vector<SymbolBody *> &getSymbols() override { return SymbolBodies; }
private:
std::error_code parse() override;
- MemoryBufferRef MBRef;
+ MemoryBufferRef MB;
std::vector<SymbolBody *> SymbolBodies;
llvm::BumpPtrAllocator Alloc;
StringAllocator StringAlloc;
if (Magic != file_magic::coff_object)
return make_dynamic_error_code("unknown file type");
- std::unique_ptr<InputFile> Obj(new ObjectFile(MBRef.getBufferIdentifier(), MBRef));
+ std::unique_ptr<InputFile> Obj(new ObjectFile(MBRef));
Obj->setParentName(File->getName());
return std::move(Obj);
}