Skip to content

Commit de3a485

Browse files
[NFC][PPC] Refactor TOC representation to allow several entries for the same symbol
We currently represent TOC entries by an MCSymbol. This is not enough in some situations. For example, when accessing an initialized TLS variable v on AIX using the general dynamic model, we need to generate the two following entries for v: .tc .v[TC],v@m .tc v[TC],v One is for the region handle (with the @m relocation), the other is for the variable offset. This refactoring allows storing several entries for the same symbol with different VariantKind in the TOC. If the VariantKind is not specified, we default to VK_None. The AIX TLS implementation using this refactoring to generate the two entries will be posted in a subsequent patch. Patched By: bsaleil Reviewed By: sfertile Differential Revision: https://reviews.llvm.org/D96346
1 parent 9f38001 commit de3a485

File tree

1 file changed

+44
-8
lines changed

1 file changed

+44
-8
lines changed

llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,42 @@ using namespace llvm::XCOFF;
7878

7979
#define DEBUG_TYPE "asmprinter"
8080

81+
// Specialize DenseMapInfo to allow
82+
// std::pair<const MCSymbol *, MCSymbolRefExpr::VariantKind> in DenseMap.
83+
// This specialization is needed here because that type is used as keys in the
84+
// map representing TOC entries.
85+
template <>
86+
struct DenseMapInfo<std::pair<const MCSymbol *, MCSymbolRefExpr::VariantKind>> {
87+
using TOCKey = std::pair<const MCSymbol *, MCSymbolRefExpr::VariantKind>;
88+
89+
static inline TOCKey getEmptyKey() {
90+
return {nullptr, MCSymbolRefExpr::VariantKind::VK_None};
91+
}
92+
static inline TOCKey getTombstoneKey() {
93+
return {nullptr, MCSymbolRefExpr::VariantKind::VK_Invalid};
94+
}
95+
static unsigned getHashValue(const TOCKey &PairVal) {
96+
return detail::combineHashValue(
97+
DenseMapInfo<const MCSymbol *>::getHashValue(PairVal.first),
98+
DenseMapInfo<int>::getHashValue(PairVal.second));
99+
}
100+
static bool isEqual(const TOCKey &A, const TOCKey &B) { return A == B; }
101+
};
102+
81103
namespace {
82104

83105
class PPCAsmPrinter : public AsmPrinter {
84106
protected:
85-
MapVector<const MCSymbol *, MCSymbol *> TOC;
107+
// For TLS on AIX, we need to be able to identify TOC entries of specific
108+
// VariantKind so we can add the right relocations when we generate the
109+
// entries. So each entry is represented by a pair of MCSymbol and
110+
// VariantKind. For example, we need to be able to identify the following
111+
// entry as a TLSGD entry so we can add the @m relocation:
112+
// .tc .i[TC],i[TL]@m
113+
// By default, VK_None is used for the VariantKind.
114+
MapVector<std::pair<const MCSymbol *, MCSymbolRefExpr::VariantKind>,
115+
MCSymbol *>
116+
TOC;
86117
const PPCSubtarget *Subtarget = nullptr;
87118
StackMaps SM;
88119

@@ -93,7 +124,9 @@ class PPCAsmPrinter : public AsmPrinter {
93124

94125
StringRef getPassName() const override { return "PowerPC Assembly Printer"; }
95126

96-
MCSymbol *lookUpOrCreateTOCEntry(const MCSymbol *Sym);
127+
MCSymbol *lookUpOrCreateTOCEntry(const MCSymbol *Sym,
128+
MCSymbolRefExpr::VariantKind Kind =
129+
MCSymbolRefExpr::VariantKind::VK_None);
97130

98131
bool doInitialization(Module &M) override {
99132
if (!TOC.empty())
@@ -344,8 +377,10 @@ bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
344377
/// lookUpOrCreateTOCEntry -- Given a symbol, look up whether a TOC entry
345378
/// exists for it. If not, create one. Then return a symbol that references
346379
/// the TOC entry.
347-
MCSymbol *PPCAsmPrinter::lookUpOrCreateTOCEntry(const MCSymbol *Sym) {
348-
MCSymbol *&TOCEntry = TOC[Sym];
380+
MCSymbol *
381+
PPCAsmPrinter::lookUpOrCreateTOCEntry(const MCSymbol *Sym,
382+
MCSymbolRefExpr::VariantKind Kind) {
383+
MCSymbol *&TOCEntry = TOC[{Sym, Kind}];
349384
if (!TOCEntry)
350385
TOCEntry = createTempSymbol("C");
351386
return TOCEntry;
@@ -604,7 +639,8 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
604639
[IsPPC64, getTOCRelocAdjustedExprForXCOFF,
605640
this](const MCSymbol *MOSymbol, const MCExpr *Expr) -> const MCExpr * {
606641
const unsigned EntryByteSize = IsPPC64 ? 8 : 4;
607-
const auto TOCEntryIter = TOC.find(MOSymbol);
642+
const auto TOCEntryIter =
643+
TOC.find({MOSymbol, MCSymbolRefExpr::VariantKind::VK_None});
608644
assert(TOCEntryIter != TOC.end() &&
609645
"Could not find the TOC entry for this symbol.");
610646
const ptrdiff_t EntryDistanceFromTOCBase =
@@ -1505,7 +1541,7 @@ void PPCLinuxAsmPrinter::emitEndOfAsmFile(Module &M) {
15051541
OutStreamer->emitValueToAlignment(4);
15061542

15071543
for (const auto &TOCMapPair : TOC) {
1508-
const MCSymbol *const TOCEntryTarget = TOCMapPair.first;
1544+
const MCSymbol *const TOCEntryTarget = TOCMapPair.first.first;
15091545
MCSymbol *const TOCEntryLabel = TOCMapPair.second;
15101546

15111547
OutStreamer->emitLabel(TOCEntryLabel);
@@ -2163,12 +2199,12 @@ void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) {
21632199
for (auto &I : TOC) {
21642200
// Setup the csect for the current TC entry.
21652201
MCSectionXCOFF *TCEntry = cast<MCSectionXCOFF>(
2166-
getObjFileLowering().getSectionForTOCEntry(I.first, TM));
2202+
getObjFileLowering().getSectionForTOCEntry(I.first.first, TM));
21672203
OutStreamer->SwitchSection(TCEntry);
21682204

21692205
OutStreamer->emitLabel(I.second);
21702206
if (TS != nullptr)
2171-
TS->emitTCEntry(*I.first);
2207+
TS->emitTCEntry(*I.first.first);
21722208
}
21732209
}
21742210

0 commit comments

Comments
 (0)