diff --git a/lld/COFF/Driver.cpp b/lld/COFF/Driver.cpp --- a/lld/COFF/Driver.cpp +++ b/lld/COFF/Driver.cpp @@ -208,17 +208,11 @@ ctx.symtab.addFile(make(ctx, mbref)); break; case file_magic::bitcode: - if (lazy) - ctx.symtab.addFile(make(ctx, mbref)); - else - ctx.symtab.addFile(make(ctx, mbref, "", 0)); + ctx.symtab.addFile(make(ctx, mbref, "", 0, lazy)); break; case file_magic::coff_object: case file_magic::coff_import_library: - if (lazy) - ctx.symtab.addFile(make(ctx, mbref)); - else - ctx.symtab.addFile(make(ctx, mbref)); + ctx.symtab.addFile(make(ctx, mbref, lazy)); break; case file_magic::pdb: ctx.symtab.addFile(make(ctx, mbref)); @@ -282,7 +276,8 @@ if (magic == file_magic::coff_object) { obj = make(ctx, mb); } else if (magic == file_magic::bitcode) { - obj = make(ctx, mb, parentName, offsetInArchive); + obj = + make(ctx, mb, parentName, offsetInArchive, /*lazy=*/false); } else { error("unknown file type: " + mb.getBufferIdentifier()); return; diff --git a/lld/COFF/InputFiles.h b/lld/COFF/InputFiles.h --- a/lld/COFF/InputFiles.h +++ b/lld/COFF/InputFiles.h @@ -95,13 +95,17 @@ COFFLinkerContext &ctx; protected: - InputFile(COFFLinkerContext &c, Kind k, MemoryBufferRef m) - : mb(m), ctx(c), fileKind(k) {} + InputFile(COFFLinkerContext &c, Kind k, MemoryBufferRef m, bool lazy = false) + : mb(m), ctx(c), fileKind(k), lazy(lazy) {} StringRef directives; private: const Kind fileKind; + +public: + // True if this is a lazy ObjFile or BitcodeFile. + bool lazy = false; }; // .lib or .a file. @@ -121,33 +125,14 @@ llvm::DenseSet seen; }; -// .obj or .o file between -start-lib and -end-lib. -class LazyObjFile : public InputFile { -public: - explicit LazyObjFile(COFFLinkerContext &ctx, MemoryBufferRef m) - : InputFile(ctx, LazyObjectKind, m) {} - static bool classof(const InputFile *f) { - return f->kind() == LazyObjectKind; - } - // Makes this object file part of the link. - void fetch(); - // Adds the symbols in this file to the symbol table as LazyObject symbols. - void parse() override; - -private: - std::vector symbols; -}; - // .obj or .o file. This may be a member of an archive file. class ObjFile : public InputFile { public: - explicit ObjFile(COFFLinkerContext &ctx, MemoryBufferRef m) - : InputFile(ctx, ObjectKind, m) {} - explicit ObjFile(COFFLinkerContext &ctx, MemoryBufferRef m, - std::vector &&symbols) - : InputFile(ctx, ObjectKind, m), symbols(std::move(symbols)) {} + explicit ObjFile(COFFLinkerContext &ctx, MemoryBufferRef m, bool lazy = false) + : InputFile(ctx, ObjectKind, m, lazy) {} static bool classof(const InputFile *f) { return f->kind() == ObjectKind; } void parse() override; + void parseLazy(); MachineTypes getMachineType() override; ArrayRef getChunks() { return chunks; } ArrayRef getDebugChunks() { return debugChunks; } @@ -380,15 +365,14 @@ // Used for LTO. class BitcodeFile : public InputFile { public: - BitcodeFile(COFFLinkerContext &ctx, MemoryBufferRef mb, StringRef archiveName, - uint64_t offsetInArchive); - explicit BitcodeFile(COFFLinkerContext &ctx, MemoryBufferRef m, + explicit BitcodeFile(COFFLinkerContext &ctx, MemoryBufferRef mb, StringRef archiveName, uint64_t offsetInArchive, - std::vector &&symbols); + bool lazy); ~BitcodeFile(); static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; } ArrayRef getSymbols() { return symbols; } MachineTypes getMachineType() override; + void parseLazy(); std::unique_ptr obj; private: diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp --- a/lld/COFF/InputFiles.cpp +++ b/lld/COFF/InputFiles.cpp @@ -135,31 +135,7 @@ return v; } -void LazyObjFile::fetch() { - if (mb.getBuffer().empty()) - return; - - InputFile *file; - if (isBitcode(mb)) - file = make(ctx, mb, "", 0, std::move(symbols)); - else - file = make(ctx, mb, std::move(symbols)); - mb = {}; - ctx.symtab.addFile(file); -} - -void LazyObjFile::parse() { - if (isBitcode(this->mb)) { - // Bitcode file. - std::unique_ptr obj = - CHECK(lto::InputFile::create(this->mb), this); - for (const lto::InputFile::Symbol &sym : obj->symbols()) { - if (!sym.isUndefined()) - ctx.symtab.addLazyObject(this, sym.getName()); - } - return; - } - +void ObjFile::parseLazy() { // Native object file. std::unique_ptr coffObjPtr = CHECK(createBinary(mb), this); COFFObjectFile *coffObj = cast(coffObjPtr.get()); @@ -1005,14 +981,10 @@ name, cast_or_null(impSym), hdr->Machine); } -BitcodeFile::BitcodeFile(COFFLinkerContext &ctx, MemoryBufferRef mb, - StringRef archiveName, uint64_t offsetInArchive) - : BitcodeFile(ctx, mb, archiveName, offsetInArchive, {}) {} - BitcodeFile::BitcodeFile(COFFLinkerContext &ctx, MemoryBufferRef mb, StringRef archiveName, uint64_t offsetInArchive, - std::vector &&symbols) - : InputFile(ctx, BitcodeKind, mb), symbols(std::move(symbols)) { + bool lazy) + : InputFile(ctx, BitcodeKind, mb, lazy) { std::string path = mb.getBufferIdentifier().str(); if (config->thinLTOIndexOnly) path = replaceThinLTOSuffix(mb.getBufferIdentifier()); @@ -1107,6 +1079,13 @@ directives = obj->getCOFFLinkerOpts(); } +void BitcodeFile::parseLazy() { + std::unique_ptr obj = CHECK(lto::InputFile::create(mb), this); + for (const lto::InputFile::Symbol &sym : obj->symbols()) + if (!sym.isUndefined()) + ctx.symtab.addLazyObject(this, sym.getName()); +} + MachineTypes BitcodeFile::getMachineType() { switch (Triple(obj->getTargetTriple()).getArch()) { case Triple::x86_64: diff --git a/lld/COFF/SymbolTable.h b/lld/COFF/SymbolTable.h --- a/lld/COFF/SymbolTable.h +++ b/lld/COFF/SymbolTable.h @@ -91,7 +91,7 @@ Symbol *addUndefined(StringRef name, InputFile *f, bool isWeakAlias); void addLazyArchive(ArchiveFile *f, const Archive::Symbol &sym); - void addLazyObject(LazyObjFile *f, StringRef n); + void addLazyObject(InputFile *f, StringRef n); void addLazyDLLSymbol(DLLFile *f, DLLFile::Symbol *sym, StringRef n); Symbol *addAbsolute(StringRef n, COFFSymbolRef s); Symbol *addRegular(InputFile *f, StringRef n, diff --git a/lld/COFF/SymbolTable.cpp b/lld/COFF/SymbolTable.cpp --- a/lld/COFF/SymbolTable.cpp +++ b/lld/COFF/SymbolTable.cpp @@ -37,7 +37,21 @@ void SymbolTable::addFile(InputFile *file) { log("Reading " + toString(file)); - file->parse(); + if (file->lazy) { + if (auto *f = dyn_cast(file)) + f->parseLazy(); + else + cast(file)->parseLazy(); + } else { + file->parse(); + if (auto *f = dyn_cast(file)) { + ctx.objFileInstances.push_back(f); + } else if (auto *f = dyn_cast(file)) { + ctx.bitcodeFileInstances.push_back(f); + } else if (auto *f = dyn_cast(file)) { + ctx.importFileInstances.push_back(f); + } + } MachineTypes mt = file->getMachineType(); if (config->machine == IMAGE_FILE_MACHINE_UNKNOWN) { @@ -48,14 +62,6 @@ return; } - if (auto *f = dyn_cast(file)) { - ctx.objFileInstances.push_back(f); - } else if (auto *f = dyn_cast(file)) { - ctx.bitcodeFileInstances.push_back(f); - } else if (auto *f = dyn_cast(file)) { - ctx.importFileInstances.push_back(f); - } - driver->parseDirectives(file); } @@ -75,9 +81,11 @@ l->file->addMember(l->sym); break; } - case Symbol::Kind::LazyObjectKind: - cast(s)->file->fetch(); + case Symbol::Kind::LazyObjectKind: { + InputFile *file = cast(s)->file; + file->ctx.symtab.addFile(file); break; + } case Symbol::Kind::LazyDLLSymbolKind: { auto *l = cast(s); l->file->makeImport(l->sym); @@ -562,7 +570,7 @@ f->addMember(sym); } -void SymbolTable::addLazyObject(LazyObjFile *f, StringRef n) { +void SymbolTable::addLazyObject(InputFile *f, StringRef n) { Symbol *s; bool wasInserted; std::tie(s, wasInserted) = insert(n, f); @@ -574,7 +582,9 @@ if (!u || u->weakAlias || s->pendingArchiveLoad) return; s->pendingArchiveLoad = true; - f->fetch(); + assert(f->lazy); + f->lazy = false; + ctx.symtab.addFile(f); } void SymbolTable::addLazyDLLSymbol(DLLFile *f, DLLFile::Symbol *sym, diff --git a/lld/COFF/Symbols.h b/lld/COFF/Symbols.h --- a/lld/COFF/Symbols.h +++ b/lld/COFF/Symbols.h @@ -305,10 +305,9 @@ class LazyObject : public Symbol { public: - LazyObject(LazyObjFile *f, StringRef n) - : Symbol(LazyObjectKind, n), file(f) {} + LazyObject(InputFile *f, StringRef n) : Symbol(LazyObjectKind, n), file(f) {} static bool classof(const Symbol *s) { return s->kind() == LazyObjectKind; } - LazyObjFile *file; + InputFile *file; }; // MinGW only.