@@ -200,28 +200,13 @@ static bool compatibleMachineType(COFFLinkerContext &ctx, MachineTypes mt) {
200200 }
201201}
202202
203- void LinkerDriver::addFile (InputFile *file) {
204- Log (ctx) << " Reading " << toString (file);
205- if (file->lazy ) {
206- if (auto *f = dyn_cast<BitcodeFile>(file))
207- f->parseLazy ();
208- else
209- cast<ObjFile>(file)->parseLazy ();
210- } else {
211- file->parse ();
212- if (auto *f = dyn_cast<ObjFile>(file)) {
213- ctx.objFileInstances .push_back (f);
214- } else if (auto *f = dyn_cast<BitcodeFile>(file)) {
215- if (ltoCompilationDone) {
216- Err (ctx) << " LTO object file " << toString (file)
217- << " linked in after "
218- " doing LTO compilation." ;
219- }
220- f->symtab .bitcodeFileInstances .push_back (f);
221- } else if (auto *f = dyn_cast<ImportFile>(file)) {
222- ctx.importFileInstances .push_back (f);
223- }
203+ void LinkerDriver::addFile (InputFile *file, CmdLineArchive *inCmdLineArchive) {
204+ if (inCmdLineArchive) {
205+ inCmdLineArchive->addInputFile (file); // schedule for lazy parsing
206+ return ;
224207 }
208+ Log (ctx) << " Reading " << toString (file);
209+ file->maybeParse ();
225210
226211 MachineTypes mt = file->getMachineType ();
227212 // The ARM64EC target must be explicitly specified and cannot be inferred.
@@ -259,17 +244,24 @@ MemoryBufferRef LinkerDriver::takeBuffer(std::unique_ptr<MemoryBuffer> mb) {
259244}
260245
261246void LinkerDriver::addBuffer (std::unique_ptr<MemoryBuffer> mb,
262- bool wholeArchive, bool lazy) {
247+ bool wholeArchive,
248+ CmdLineArchive *inCmdLineArchive) {
263249 StringRef filename = mb->getBufferIdentifier ();
264250
265251 MemoryBufferRef mbref = takeBuffer (std::move (mb));
266252
267253 // File type is detected by contents, not by file extension.
268254 switch (identify_magic (mbref.getBuffer ())) {
269255 case file_magic::windows_resource:
256+ assert (!inCmdLineArchive &&
257+ " Cannot specify a RES file inside a --start-lib/--end-lib group." );
270258 resources.push_back (mbref);
271259 break ;
272260 case file_magic::archive:
261+ // FIXME: We could later support --start-lib/--end-lib groups, to allow for
262+ // "extending" an existing archive/LIB.
263+ assert (!inCmdLineArchive &&
264+ " Cannot specify a LIB file inside a --start-lib/--end-lib group." );
273265 if (wholeArchive) {
274266 std::unique_ptr<Archive> file =
275267 CHECK (Archive::create (mbref), filename + " : failed to parse archive" );
@@ -284,13 +276,15 @@ void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,
284276 addFile (make<ArchiveFile>(ctx, mbref));
285277 break ;
286278 case file_magic::bitcode:
287- addFile (BitcodeFile::create (ctx, mbref, " " , 0 , lazy) );
279+ addFile (BitcodeFile::create (ctx, mbref, " " , 0 ), inCmdLineArchive );
288280 break ;
289281 case file_magic::coff_object:
290282 case file_magic::coff_import_library:
291- addFile (ObjFile::create (ctx, mbref, lazy) );
283+ addFile (ObjFile::create (ctx, mbref), inCmdLineArchive );
292284 break ;
293285 case file_magic::pdb:
286+ assert (!inCmdLineArchive &&
287+ " Cannot specify a PDB file inside a --start-lib/--end-lib group." );
294288 addFile (make<PDBInputFile>(ctx, mbref));
295289 break ;
296290 case file_magic::coff_cl_gl_object:
@@ -299,6 +293,9 @@ void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,
299293 break ;
300294 case file_magic::pecoff_executable:
301295 if (ctx.config .mingw ) {
296+ assert (
297+ !inCmdLineArchive &&
298+ " Cannot specify a PE/EXE file inside a --start-lib/--end-lib group." );
302299 addFile (make<DLLFile>(ctx.symtab , mbref));
303300 break ;
304301 }
@@ -315,7 +312,9 @@ void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,
315312 }
316313}
317314
318- void LinkerDriver::enqueuePath (StringRef path, bool wholeArchive, bool lazy) {
315+ void LinkerDriver::enqueuePath (
316+ StringRef path, bool wholeArchive,
317+ std::optional<std::shared_future<CmdLineArchive *>> inCmdLineArchive) {
319318 auto future = std::make_shared<std::future<MBErrPair>>(
320319 createFutureForFile (std::string (path)));
321320 std::string pathStr = std::string (path);
@@ -354,7 +353,9 @@ void LinkerDriver::enqueuePath(StringRef path, bool wholeArchive, bool lazy) {
354353 else
355354 Err (ctx) << msg << " ; did you mean '" << nearest << " '" ;
356355 } else
357- ctx.driver .addBuffer (std::move (mb), wholeArchive, lazy);
356+ ctx.driver .addBuffer (std::move (mb), wholeArchive,
357+ inCmdLineArchive ? inCmdLineArchive->get ()
358+ : nullptr );
358359 });
359360}
360361
@@ -373,8 +374,7 @@ void LinkerDriver::addArchiveBuffer(MemoryBufferRef mb, StringRef symName,
373374 if (magic == file_magic::coff_object) {
374375 obj = ObjFile::create (ctx, mb);
375376 } else if (magic == file_magic::bitcode) {
376- obj = BitcodeFile::create (ctx, mb, parentName, offsetInArchive,
377- /* lazy=*/ false );
377+ obj = BitcodeFile::create (ctx, mb, parentName, offsetInArchive);
378378 } else if (magic == file_magic::coff_cl_gl_object) {
379379 Err (ctx) << mb.getBufferIdentifier ()
380380 << " : is not a native COFF file. Recompile without /GL?" ;
@@ -494,7 +494,7 @@ void LinkerDriver::parseDirectives(InputFile *file) {
494494 break ;
495495 case OPT_defaultlib:
496496 if (std::optional<StringRef> path = findLibIfNew (arg->getValue ()))
497- enqueuePath (*path, false , false );
497+ enqueuePath (*path);
498498 break ;
499499 case OPT_entry:
500500 if (!arg->getValue ()[0 ])
@@ -2177,32 +2177,50 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
21772177 // and OPT_end_lib.
21782178 {
21792179 llvm::TimeTraceScope timeScope2 (" Parse & queue inputs" );
2180- bool inLib = false ;
2180+ std::optional<std::shared_future<CmdLineArchive *>> inCmdLineArchive ;
21812181 for (auto *arg : args) {
21822182 switch (arg->getOption ().getID ()) {
21832183 case OPT_end_lib:
2184- if (!inLib)
2184+ if (!inCmdLineArchive) {
21852185 Err (ctx) << " stray " << arg->getSpelling ();
2186- inLib = false ;
2186+ } else {
2187+ enqueueTask ([=]() { inCmdLineArchive->get ()->maybeParse (); });
2188+ inCmdLineArchive = std::nullopt ;
2189+ }
21872190 break ;
21882191 case OPT_start_lib:
2189- if (inLib)
2192+ if (inCmdLineArchive) {
21902193 Err (ctx) << " nested " << arg->getSpelling ();
2191- inLib = true ;
2194+ } else {
2195+ auto a = std::make_shared<std::promise<CmdLineArchive *>>();
2196+ inCmdLineArchive = a->get_future ().share ();
2197+ enqueueTask ([&, a]() {
2198+ // In is important to create a fake archive here so that we
2199+ // remember its placement on the command-line. This will be
2200+ // later needed to resolve symbols in the archive order required
2201+ // by the MSVC specification.
2202+ a->set_value (make<CmdLineArchive>(
2203+ ctx.symtab , MemoryBufferRef ({}, " <cmdline-lib>" )));
2204+ });
2205+ }
21922206 break ;
21932207 case OPT_wholearchive_file:
21942208 if (std::optional<StringRef> path = findFileIfNew (arg->getValue ()))
2195- enqueuePath (*path, true , inLib );
2209+ enqueuePath (*path, true , inCmdLineArchive );
21962210 break ;
21972211 case OPT_INPUT:
21982212 if (std::optional<StringRef> path = findFileIfNew (arg->getValue ()))
2199- enqueuePath (*path, isWholeArchive (*path), inLib );
2213+ enqueuePath (*path, isWholeArchive (*path), inCmdLineArchive );
22002214 break ;
22012215 default :
22022216 // Ignore other options.
22032217 break ;
22042218 }
22052219 }
2220+ if (inCmdLineArchive) {
2221+ Warn (ctx) << " --start-lib with no --end-lib" ;
2222+ enqueueTask ([=]() { inCmdLineArchive->get ()->maybeParse (); });
2223+ }
22062224 }
22072225
22082226 // Read all input files given via the command line.
@@ -2236,7 +2254,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
22362254 // addWinSysRootLibSearchPaths(), which is why they are in a separate loop.
22372255 for (auto *arg : args.filtered (OPT_defaultlib))
22382256 if (std::optional<StringRef> path = findLibIfNew (arg->getValue ()))
2239- enqueuePath (*path, false , false );
2257+ enqueuePath (*path);
22402258 run ();
22412259 if (errorCount ())
22422260 return ;
@@ -2553,9 +2571,11 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
25532571
25542572 if (args.hasArg (OPT_include_optional)) {
25552573 // Handle /includeoptional
2556- for (auto *arg : args.filtered (OPT_include_optional))
2557- if (isa_and_nonnull<LazyArchive>(symtab.find (arg->getValue ())))
2574+ for (auto *arg : args.filtered (OPT_include_optional)) {
2575+ Symbol *sym = ctx.symtab .find (arg->getValue ());
2576+ if (sym && (isa<LazyArchive>(sym) || isa<LazyObject>(sym)))
25582577 symtab.addGCRoot (arg->getValue ());
2578+ }
25592579 }
25602580 });
25612581 } while (run ());
@@ -2720,7 +2740,7 @@ void LinkerDriver::linkerMain(ArrayRef<const char *> argsArr) {
27202740 // /manifestdependency: enables /manifest unless an explicit /manifest:no is
27212741 // also passed.
27222742 if (config->manifest == Configuration::Embed)
2723- addBuffer (createManifestRes (), false , false );
2743+ addBuffer (createManifestRes (), false );
27242744 else if (config->manifest == Configuration::SideBySide ||
27252745 (config->manifest == Configuration::Default &&
27262746 !config->manifestDependencies .empty ()))
0 commit comments