diff --git a/llvm/include/llvm/MC/MCExpr.h b/llvm/include/llvm/MC/MCExpr.h --- a/llvm/include/llvm/MC/MCExpr.h +++ b/llvm/include/llvm/MC/MCExpr.h @@ -194,6 +194,7 @@ enum VariantKind : uint16_t { VK_None, VK_Invalid, + VK_Empty, VK_GOT, VK_GOTOFF, @@ -416,6 +417,23 @@ } }; +// Specialize DenseMapInfo to allow MCSymbolRefExpr::VariantKind in DenseMap +template <> struct DenseMapInfo { + static inline MCSymbolRefExpr::VariantKind getEmptyKey() { + return MCSymbolRefExpr::VariantKind::VK_Empty; + } + static inline MCSymbolRefExpr::VariantKind getTombstoneKey() { + return MCSymbolRefExpr::VariantKind::VK_Invalid; + } + static unsigned getHashValue(const MCSymbolRefExpr::VariantKind &V) { + return DenseMapInfo::getHashValue(V); + } + static bool isEqual(const MCSymbolRefExpr::VariantKind &A, + const MCSymbolRefExpr::VariantKind &B) { + return A == B; + } +}; + /// Unary assembler expressions. class MCUnaryExpr : public MCExpr { public: diff --git a/llvm/lib/MC/MCExpr.cpp b/llvm/lib/MC/MCExpr.cpp --- a/llvm/lib/MC/MCExpr.cpp +++ b/llvm/lib/MC/MCExpr.cpp @@ -222,6 +222,7 @@ switch (Kind) { case VK_Invalid: return "<>"; case VK_None: return "<>"; + case VK_Empty: return "<>"; case VK_DTPOFF: return "DTPOFF"; case VK_DTPREL: return "DTPREL"; 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 @@ -82,7 +82,16 @@ 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 +102,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 +354,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 +616,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 +1518,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); @@ -2157,12 +2171,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); } }