From 270119b876cc41fa828b5da209225a543d02adbb Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Mon, 23 Jul 2018 23:51:19 +0000 Subject: [WebAssembly] Add support for --whole-archive. Subscribers: dschuff, jgravelle-google, aheejin, sunfish, llvm-commits Differential Revision: https://reviews.llvm.org/D49706 --- lld/wasm/Driver.cpp | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) (limited to 'lld/wasm/Driver.cpp') 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 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 static getArchiveMembers( + MemoryBufferRef MB) { + std::unique_ptr File = + CHECK(Archive::create(MB), + MB.getBufferIdentifier() + ": failed to parse archive"); + + std::vector V; + Error Err = Error::success(); + for (const ErrorOr &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 &MB : File->takeThinBuffers()) + make>(std::move(MB)); + + return V; +} + void LinkerDriver::addFile(StringRef Path) { Optional 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(MBRef)); + case file_magic::wasm_object: + Files.push_back(createObjectFile(MBRef)); break; default: - Files.push_back(make(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; } } } -- cgit v1.2.3