diff options
-rw-r--r-- | lld/ELF/InputFiles.cpp | 17 | ||||
-rw-r--r-- | lld/ELF/InputFiles.h | 2 | ||||
-rw-r--r-- | lld/ELF/SymbolTable.cpp | 6 | ||||
-rw-r--r-- | lld/test/ELF/lto/comdat.ll | 21 |
4 files changed, 41 insertions, 5 deletions
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 78abcf95fbe..8b8cf02a8de 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -13,6 +13,7 @@ #include "Symbols.h" #include "llvm/ADT/STLExtras.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" #include "llvm/Object/IRObjectFile.h" #include "llvm/Support/raw_ostream.h" @@ -441,13 +442,27 @@ bool BitcodeFile::classof(const InputFile *F) { return F->kind() == BitcodeKind; } -void BitcodeFile::parse() { +void BitcodeFile::parse(DenseSet<StringRef> &ComdatGroups) { LLVMContext Context; ErrorOr<std::unique_ptr<IRObjectFile>> ObjOrErr = IRObjectFile::create(MB, Context); fatal(ObjOrErr); IRObjectFile &Obj = **ObjOrErr; + const Module &M = Obj.getModule(); + + DenseSet<const Comdat *> KeptComdats; + for (const auto &P : M.getComdatSymbolTable()) { + StringRef N = Saver.save(P.first()); + if (ComdatGroups.insert(N).second) + KeptComdats.insert(&P.second); + } + for (const BasicSymbolRef &Sym : Obj.symbols()) { + if (const GlobalValue *GV = Obj.getSymbolGV(Sym.getRawDataRefImpl())) + if (const Comdat *C = GV->getComdat()) + if (!KeptComdats.count(C)) + continue; + SmallString<64> Name; raw_svector_ostream OS(Name); Sym.printName(OS); diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 18debd420b5..48fe27d31f2 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -183,7 +183,7 @@ class BitcodeFile : public InputFile { public: explicit BitcodeFile(MemoryBufferRef M); static bool classof(const InputFile *F); - void parse(); + void parse(llvm::DenseSet<StringRef> &ComdatGroups); ArrayRef<SymbolBody *> getSymbols() { return SymbolBodies; } private: diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index 095ad86764c..6892968cf04 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -82,7 +82,7 @@ void SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) { // LLVM bitcode file. if (auto *F = dyn_cast<BitcodeFile>(FileP)) { BitcodeFiles.emplace_back(cast<BitcodeFile>(File.release())); - F->parse(); + F->parse(ComdatGroups); for (SymbolBody *B : F->getSymbols()) resolve(B); return; @@ -151,8 +151,8 @@ template <class ELFT> void SymbolTable<ELFT>::addCombinedLtoObject() { if (BitcodeFiles.empty()) return; ObjectFile<ELFT> *Obj = createCombinedLtoObject(); - // FIXME: We probably have to ignore comdats here. - Obj->parse(ComdatGroups); + llvm::DenseSet<StringRef> DummyGroups; + Obj->parse(DummyGroups); for (SymbolBody *Body : Obj->getSymbols()) { Symbol *Sym = insert(Body); Sym->Body = Body; diff --git a/lld/test/ELF/lto/comdat.ll b/lld/test/ELF/lto/comdat.ll new file mode 100644 index 00000000000..e1384d0abd2 --- /dev/null +++ b/lld/test/ELF/lto/comdat.ll @@ -0,0 +1,21 @@ +; REQUIRES: x86 +; RUN: llvm-as %s -o %t.o +; RUN: ld.lld -m elf_x86_64 %t.o %t.o -o %t.so -shared +; RUN: llvm-readobj -t %t.so | FileCheck %s + +; CHECK: Name: foo +; CHECK-NEXT: Value: +; CHECK-NEXT: Size: 1 +; CHECK-NEXT: Binding: Global +; CHECK-NEXT: Type: Function +; CHECK-NEXT: Other: 0 +; CHECK-NEXT: Section: .text + +target triple = "x86_64-unknown-linux-gnu" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +$foo = comdat any +define void @foo() comdat { + ret void +} + |