diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1500,7 +1500,7 @@ // Add all files to the symbol table. This will add almost all // symbols that we need to the symbol table. for (InputFile *F : Files) - Symtab->addFile(F); + parseFile(F); // Now that we have every file, we can decide if we will need a // dynamic symbol table. diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -54,6 +54,9 @@ // Opens a given file. llvm::Optional readFile(StringRef Path); +// Add symbols in File to the symbol table. +template void parseFile(InputFile *File); + // The root class of input files. class InputFile { public: diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -78,6 +78,88 @@ return MBRef; } +// All input object files must be for the same architecture +// (e.g. it does not make sense to link x86 object files with +// MIPS object files.) This function checks for that error. +static bool isCompatible(InputFile *File) { + if (!File->isElf() && !isa(File)) + return true; + + if (File->EKind == Config->EKind && File->EMachine == Config->EMachine) { + if (Config->EMachine != EM_MIPS) + return true; + if (isMipsN32Abi(File) == Config->MipsN32Abi) + return true; + } + + if (!Config->Emulation.empty()) { + error(toString(File) + " is incompatible with " + Config->Emulation); + } else { + InputFile *Existing; + if (!ObjectFiles.empty()) + Existing = ObjectFiles[0]; + else if (!SharedFiles.empty()) + Existing = SharedFiles[0]; + else + Existing = BitcodeFiles[0]; + + error(toString(File) + " is incompatible with " + toString(Existing)); + } + + return false; +} + +// Add symbols in File to the symbol table. +template void elf::parseFile(InputFile *File) { + // Comdat groups define "link once" sections. If two comdat groups have the + // same name, only one of them is linked, and the other is ignored. This set + // is used to uniquify them. + static llvm::DenseSet ComdatGroups; + + if (!isCompatible(File)) + return; + + // Binary file + if (auto *F = dyn_cast(File)) { + BinaryFiles.push_back(F); + F->parse(); + return; + } + + // .a file + if (auto *F = dyn_cast(File)) { + F->parse(); + return; + } + + // Lazy object file + if (auto *F = dyn_cast(File)) { + LazyObjFiles.push_back(F); + F->parse(); + return; + } + + if (Config->Trace) + message(toString(File)); + + // .so file + if (auto *F = dyn_cast(File)) { + F->parse(); + return; + } + + // LLVM bitcode file + if (auto *F = dyn_cast(File)) { + BitcodeFiles.push_back(F); + F->parse(ComdatGroups); + return; + } + + // Regular object file + ObjectFiles.push_back(File); + cast>(File)->parse(ComdatGroups); +} + // Concatenates arguments to construct a string representing an error location. static std::string createFileLineMsg(StringRef Path, unsigned Line) { std::string Filename = path::filename(Path); @@ -1359,6 +1441,11 @@ return Path; } +template void elf::parseFile(InputFile *); +template void elf::parseFile(InputFile *); +template void elf::parseFile(InputFile *); +template void elf::parseFile(InputFile *); + template void ArchiveFile::parse(); template void ArchiveFile::parse(); template void ArchiveFile::parse(); diff --git a/lld/ELF/SymbolTable.h b/lld/ELF/SymbolTable.h --- a/lld/ELF/SymbolTable.h +++ b/lld/ELF/SymbolTable.h @@ -34,7 +34,6 @@ // is one add* function per symbol type. class SymbolTable { public: - template void addFile(InputFile *File); template void addCombinedLTOObject(); void wrap(Symbol *Sym, Symbol *Real, Symbol *Wrap); diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -32,81 +32,6 @@ SymbolTable *elf::Symtab; -static InputFile *getFirstElf() { - if (!ObjectFiles.empty()) - return ObjectFiles[0]; - if (!SharedFiles.empty()) - return SharedFiles[0]; - return BitcodeFiles[0]; -} - -// All input object files must be for the same architecture -// (e.g. it does not make sense to link x86 object files with -// MIPS object files.) This function checks for that error. -static bool isCompatible(InputFile *F) { - if (!F->isElf() && !isa(F)) - return true; - - if (F->EKind == Config->EKind && F->EMachine == Config->EMachine) { - if (Config->EMachine != EM_MIPS) - return true; - if (isMipsN32Abi(F) == Config->MipsN32Abi) - return true; - } - - if (!Config->Emulation.empty()) - error(toString(F) + " is incompatible with " + Config->Emulation); - else - error(toString(F) + " is incompatible with " + toString(getFirstElf())); - return false; -} - -// Add symbols in File to the symbol table. -template void SymbolTable::addFile(InputFile *File) { - if (!isCompatible(File)) - return; - - // Binary file - if (auto *F = dyn_cast(File)) { - BinaryFiles.push_back(F); - F->parse(); - return; - } - - // .a file - if (auto *F = dyn_cast(File)) { - F->parse(); - return; - } - - // Lazy object file - if (auto *F = dyn_cast(File)) { - LazyObjFiles.push_back(F); - F->parse(); - return; - } - - if (Config->Trace) - message(toString(File)); - - // .so file - if (auto *F = dyn_cast(File)) { - F->parse(); - return; - } - - // LLVM bitcode file - if (auto *F = dyn_cast(File)) { - BitcodeFiles.push_back(F); - F->parse(ComdatGroups); - return; - } - - // Regular object file - ObjectFiles.push_back(File); - cast>(File)->parse(ComdatGroups); -} - // This function is where all the optimizations of link-time // optimization happens. When LTO is in use, some input files are // not in native object file format but in the LLVM bitcode format. @@ -539,7 +464,7 @@ } if (InputFile *F = File.fetch(Sym)) - addFile(F); + parseFile(F); } template @@ -563,19 +488,19 @@ } if (InputFile *F = File.fetch()) - addFile(F); + parseFile(F); } template void SymbolTable::fetchLazy(Symbol *Sym) { if (auto *S = dyn_cast(Sym)) { if (InputFile *File = S->fetch()) - addFile(File); + parseFile(File); return; } auto *S = cast(Sym); if (InputFile *File = cast(S->File)->fetch()) - addFile(File); + parseFile(File); } // Initialize DemangledSyms with a map from demangled symbols to symbol @@ -739,11 +664,6 @@ Sym->parseSymbolVersion(); } -template void SymbolTable::addFile(InputFile *); -template void SymbolTable::addFile(InputFile *); -template void SymbolTable::addFile(InputFile *); -template void SymbolTable::addFile(InputFile *); - template Symbol *SymbolTable::addUndefined(StringRef, uint8_t, uint8_t, uint8_t, bool, InputFile *); template Symbol *SymbolTable::addUndefined(StringRef, uint8_t, uint8_t,