Index: include/llvm/LTO/LTO.h =================================================================== --- include/llvm/LTO/LTO.h +++ include/llvm/LTO/LTO.h @@ -106,6 +106,8 @@ // FIXME: Remove the LLVMContext once we have bitcode symbol tables. LLVMContext Ctx; std::unique_ptr Obj; + std::vector Comdats; + DenseMap ComdatMap; public: /// Create an InputFile. @@ -124,6 +126,7 @@ friend LTO; object::basic_symbol_iterator I; + const InputFile *File; const GlobalValue *GV; uint32_t Flags; SmallString<64> Name; @@ -154,7 +157,10 @@ } public: - Symbol(object::basic_symbol_iterator I) : I(I) { skip(); } + Symbol(object::basic_symbol_iterator I, const InputFile *File) + : I(I), File(File) { + skip(); + } StringRef getName() const { return Name; } StringRef getIRName() const { @@ -176,22 +182,7 @@ return GV && GV->isThreadLocal(); } - Expected getComdat() const { - if (!GV) - return ""; - const GlobalObject *GO; - if (auto *GA = dyn_cast(GV)) { - GO = GA->getBaseObject(); - if (!GO) - return make_error("Unable to determine comdat of alias!", - inconvertibleErrorCode()); - } else { - GO = cast(GV); - } - if (const Comdat *C = GO->getComdat()) - return C->getName(); - return ""; - } + Expected getComdat() const; uint64_t getCommonSize() const { assert(Flags & object::BasicSymbolRef::SF_Common); @@ -212,7 +203,8 @@ Symbol Sym; public: - symbol_iterator(object::basic_symbol_iterator I) : Sym(I) {} + symbol_iterator(object::basic_symbol_iterator I, const InputFile *File) + : Sym(I, File) {} symbol_iterator &operator++() { ++Sym.I; @@ -236,8 +228,8 @@ /// A range over the symbols in this InputFile. iterator_range symbols() { - return llvm::make_range(symbol_iterator(Obj->symbol_begin()), - symbol_iterator(Obj->symbol_end())); + return llvm::make_range(symbol_iterator(Obj->symbol_begin(), this), + symbol_iterator(Obj->symbol_end(), this)); } StringRef getDataLayoutStr() const { @@ -251,6 +243,8 @@ MemoryBufferRef getMemoryBufferRef() const { return Obj->getMemoryBufferRef(); } + + ArrayRef getComdats() const { return Comdats; } }; /// This class wraps an output stream for a native object. Most clients should Index: lib/LTO/LTO.cpp =================================================================== --- lib/LTO/LTO.cpp +++ lib/LTO/LTO.cpp @@ -217,9 +217,36 @@ File->Ctx.setDiagnosticHandler(nullptr, nullptr); + for (const auto &C : File->Obj->getModule().getComdatSymbolTable()) { + auto P = + File->ComdatMap.insert(std::make_pair(&C.second, File->Comdats.size())); + assert(P.second); + File->Comdats.push_back(C.first()); + } + return std::move(File); } +Expected InputFile::Symbol::getComdat() const { + if (!GV) + return -1; + const GlobalObject *GO; + if (auto *GA = dyn_cast(GV)) { + GO = GA->getBaseObject(); + if (!GO) + return make_error("Unable to determine comdat of alias!", + inconvertibleErrorCode()); + } else { + GO = cast(GV); + } + if (const Comdat *C = GO->getComdat()) { + auto I = File->ComdatMap.find(C); + assert(I != File->ComdatMap.end()); + return I->second; + } + return -1; +} + LTO::RegularLTOState::RegularLTOState(unsigned ParallelCodeGenParallelismLevel, Config &Conf) : ParallelCodeGenParallelismLevel(ParallelCodeGenParallelismLevel), @@ -330,8 +357,8 @@ auto ResI = Res.begin(); for (const InputFile::Symbol &Sym : - make_range(InputFile::symbol_iterator(Obj->symbol_begin()), - InputFile::symbol_iterator(Obj->symbol_end()))) { + make_range(InputFile::symbol_iterator(Obj->symbol_begin(), nullptr), + InputFile::symbol_iterator(Obj->symbol_end(), nullptr))) { assert(ResI != Res.end()); SymbolResolution Res = *ResI++; addSymbolToGlobalRes(Obj.get(), Used, Sym, Res, 0); Index: tools/gold/gold-plugin.cpp =================================================================== --- tools/gold/gold-plugin.cpp +++ tools/gold/gold-plugin.cpp @@ -526,9 +526,11 @@ sym.size = 0; sym.comdat_key = nullptr; - StringRef C = check(Sym.getComdat()); - if (!C.empty()) + int CI = check(Sym.getComdat()); + if (CI != -1) { + StringRef C = Obj->getComdats()[CI]; sym.comdat_key = strdup(C.str().c_str()); + } sym.resolution = LDPR_UNKNOWN; }