diff options
author | Sam Clegg <sbc@chromium.org> | 2018-07-23 23:51:19 +0000 |
---|---|---|
committer | Sam Clegg <sbc@chromium.org> | 2018-07-23 23:51:19 +0000 |
commit | 270119b876cc41fa828b5da209225a543d02adbb (patch) | |
tree | edc1579dbf81ce7553a6678888f7c6299e4cc028 /lld/wasm/Driver.cpp | |
parent | bc27e6ef4f291fcfb9c082a91e8ac11dccf91385 (diff) |
[WebAssembly] Add support for --whole-archive.
Subscribers: dschuff, jgravelle-google, aheejin, sunfish, llvm-commits
Differential Revision: https://reviews.llvm.org/D49706
Diffstat (limited to 'lld/wasm/Driver.cpp')
-rw-r--r-- | lld/wasm/Driver.cpp | 53 |
1 files changed, 51 insertions, 2 deletions
diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp index ccaf90fc785..329b5ae80a9 100644 --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -68,6 +68,10 @@ private: void createFiles(opt::InputArgList &Args); void addFile(StringRef Path); void addLibrary(StringRef Name); + + // True if we are in --whole-archive and --no-whole-archive. + bool InWholeArchive = false; + std::vector<InputFile *> Files; }; } // anonymous namespace @@ -180,6 +184,37 @@ static void readImportFile(StringRef Filename) { Config->AllowUndefinedSymbols.insert(Sym); } +// Returns slices of MB by parsing MB as an archive file. +// Each slice consists of a member file in the archive. +std::vector<MemoryBufferRef> static getArchiveMembers( + MemoryBufferRef MB) { + std::unique_ptr<Archive> File = + CHECK(Archive::create(MB), + MB.getBufferIdentifier() + ": failed to parse archive"); + + std::vector<MemoryBufferRef> V; + Error Err = Error::success(); + for (const ErrorOr<Archive::Child> &COrErr : File->children(Err)) { + Archive::Child C = + CHECK(COrErr, MB.getBufferIdentifier() + + ": could not get the child of the archive"); + MemoryBufferRef MBRef = + CHECK(C.getMemoryBufferRef(), + MB.getBufferIdentifier() + + ": could not get the buffer for a child of the archive"); + V.push_back(MBRef); + } + if (Err) + fatal(MB.getBufferIdentifier() + ": Archive::children failed: " + + toString(std::move(Err))); + + // Take ownership of memory buffers created for members of thin archives. + for (std::unique_ptr<MemoryBuffer> &MB : File->takeThinBuffers()) + make<std::unique_ptr<MemoryBuffer>>(std::move(MB)); + + return V; +} + void LinkerDriver::addFile(StringRef Path) { Optional<MemoryBufferRef> Buffer = readFile(Path); if (!Buffer.hasValue()) @@ -188,6 +223,13 @@ void LinkerDriver::addFile(StringRef Path) { switch (identify_magic(MBRef.getBuffer())) { case file_magic::archive: { + // Handle -whole-archive. + if (InWholeArchive) { + for (MemoryBufferRef &M : getArchiveMembers(MBRef)) + Files.push_back(createObjectFile(M)); + return; + } + SmallString<128> ImportFile = Path; path::replace_extension(ImportFile, ".imports"); if (fs::exists(ImportFile)) @@ -197,10 +239,11 @@ void LinkerDriver::addFile(StringRef Path) { return; } case file_magic::bitcode: - Files.push_back(make<BitcodeFile>(MBRef)); + case file_magic::wasm_object: + Files.push_back(createObjectFile(MBRef)); break; default: - Files.push_back(make<ObjFile>(MBRef)); + error("unknown file type: " + MBRef.getBufferIdentifier()); } } @@ -225,6 +268,12 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) { case OPT_INPUT: addFile(Arg->getValue()); break; + case OPT_whole_archive: + InWholeArchive = true; + break; + case OPT_no_whole_archive: + InWholeArchive = false; + break; } } } |