diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp --- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp +++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp @@ -78,11 +78,42 @@ #define DEBUG_TYPE "asmprinter" +// Specialize DenseMapInfo to allow +// std::pair in DenseMap. +// This specialization is needed here because that type is used as keys in the +// map representing TOC entries. +template <> +struct DenseMapInfo> { + using TOCKey = std::pair; + + static inline TOCKey getEmptyKey() { + return {nullptr, MCSymbolRefExpr::VariantKind::VK_None}; + } + static inline TOCKey getTombstoneKey() { + return {nullptr, MCSymbolRefExpr::VariantKind::VK_Invalid}; + } + static unsigned getHashValue(const TOCKey &PairVal) { + return detail::combineHashValue( + DenseMapInfo::getHashValue(PairVal.first), + DenseMapInfo::getHashValue(PairVal.second)); + } + static bool isEqual(const TOCKey &A, const TOCKey &B) { return A == B; } +}; + namespace { class PPCAsmPrinter : public AsmPrinter { protected: - MapVector TOC; + // For TLS on AIX, we need to be able to identify TOC entries of specific + // VariantKind so we can add the right relocations when we generate the + // entries. So each entry is represented by a pair of MCSymbol and + // VariantKind. For example, we need to be able to identify the following + // entry as a TLSGD entry so we can add the @m relocation: + // .tc .i[TC],i[TL]@m + // By default, VK_None is used for the VariantKind. + MapVector, + MCSymbol *> + TOC; const PPCSubtarget *Subtarget = nullptr; StackMaps SM; @@ -93,7 +124,9 @@ StringRef getPassName() const override { return "PowerPC Assembly Printer"; } - MCSymbol *lookUpOrCreateTOCEntry(const MCSymbol *Sym); + MCSymbol *lookUpOrCreateTOCEntry(const MCSymbol *Sym, + MCSymbolRefExpr::VariantKind Kind = + MCSymbolRefExpr::VariantKind::VK_None); bool doInitialization(Module &M) override { if (!TOC.empty()) @@ -343,8 +376,10 @@ /// lookUpOrCreateTOCEntry -- Given a symbol, look up whether a TOC entry /// exists for it. If not, create one. Then return a symbol that references /// the TOC entry. -MCSymbol *PPCAsmPrinter::lookUpOrCreateTOCEntry(const MCSymbol *Sym) { - MCSymbol *&TOCEntry = TOC[Sym]; +MCSymbol * +PPCAsmPrinter::lookUpOrCreateTOCEntry(const MCSymbol *Sym, + MCSymbolRefExpr::VariantKind Kind) { + MCSymbol *&TOCEntry = TOC[{Sym, Kind}]; if (!TOCEntry) TOCEntry = createTempSymbol("C"); return TOCEntry; @@ -603,7 +638,8 @@ [IsPPC64, getTOCRelocAdjustedExprForXCOFF, this](const MCSymbol *MOSymbol, const MCExpr *Expr) -> const MCExpr * { const unsigned EntryByteSize = IsPPC64 ? 8 : 4; - const auto TOCEntryIter = TOC.find(MOSymbol); + const auto TOCEntryIter = + TOC.find({MOSymbol, MCSymbolRefExpr::VariantKind::VK_None}); assert(TOCEntryIter != TOC.end() && "Could not find the TOC entry for this symbol."); const ptrdiff_t EntryDistanceFromTOCBase = @@ -1504,7 +1540,7 @@ OutStreamer->emitValueToAlignment(4); for (const auto &TOCMapPair : TOC) { - const MCSymbol *const TOCEntryTarget = TOCMapPair.first; + const MCSymbol *const TOCEntryTarget = TOCMapPair.first.first; MCSymbol *const TOCEntryLabel = TOCMapPair.second; OutStreamer->emitLabel(TOCEntryLabel); @@ -2165,12 +2201,12 @@ for (auto &I : TOC) { // Setup the csect for the current TC entry. MCSectionXCOFF *TCEntry = cast( - getObjFileLowering().getSectionForTOCEntry(I.first, TM)); + getObjFileLowering().getSectionForTOCEntry(I.first.first, TM)); OutStreamer->SwitchSection(TCEntry); OutStreamer->emitLabel(I.second); if (TS != nullptr) - TS->emitTCEntry(*I.first); + TS->emitTCEntry(*I.first.first); } }