Index: llvm/lib/CodeGen/AsmPrinter/AddressPool.h =================================================================== --- llvm/lib/CodeGen/AsmPrinter/AddressPool.h +++ llvm/lib/CodeGen/AsmPrinter/AddressPool.h @@ -17,6 +17,39 @@ class MCSection; class MCSymbol; +/// Pair of a symbol and an offset in number of bytes. +struct SymbolWithOffset { + const MCSymbol *Symbol; + int Offset; + + bool operator==(const SymbolWithOffset &O) const { + return Symbol == O.Symbol && Offset == O.Offset; + } +}; + +template <> struct DenseMapInfo { + using SymbolInfo = DenseMapInfo; + using OffsetInfo = DenseMapInfo; + using PairInfo = DenseMapInfo>; + + static SymbolWithOffset getEmptyKey() { + return {SymbolInfo::getEmptyKey(), OffsetInfo::getEmptyKey()}; + } + + static SymbolWithOffset getTombstoneKey() { + return {SymbolInfo::getTombstoneKey(), OffsetInfo::getTombstoneKey()}; + } + + static unsigned getHashValue(const SymbolWithOffset &Val) { + return PairInfo::getHashValue({Val.Symbol, Val.Offset}); + } + + static bool isEqual(const SymbolWithOffset &LHS, + const SymbolWithOffset &RHS) { + return LHS == RHS; + } +}; + // Collection of addresses for this unit and assorted labels. // A Symbol->unsigned mapping of addresses used by indirect // references. @@ -27,7 +60,7 @@ AddressPoolEntry(unsigned Number, bool TLS) : Number(Number), TLS(TLS) {} }; - DenseMap Pool; + DenseMap Pool; /// Record whether the AddressPool has been queried for an address index since /// the last "resetUsedFlag" call. Used to implement type unit fallback - a @@ -42,6 +75,10 @@ /// label/symbol. unsigned getIndex(const MCSymbol *Sym, bool TLS = false); + /// Returns the index into the address pool with the given + /// label/symbol and offset. + unsigned getIndex(SymbolWithOffset SymWithOffs, bool TLS = false); + void emit(AsmPrinter &Asm, MCSection *AddrSection); bool isEmpty() { return Pool.empty(); } Index: llvm/lib/CodeGen/AsmPrinter/AddressPool.cpp =================================================================== --- llvm/lib/CodeGen/AsmPrinter/AddressPool.cpp +++ llvm/lib/CodeGen/AsmPrinter/AddressPool.cpp @@ -18,8 +18,15 @@ unsigned AddressPool::getIndex(const MCSymbol *Sym, bool TLS) { HasBeenUsed = true; + auto IterBool = Pool.insert( + {SymbolWithOffset{Sym, 0}, AddressPoolEntry(Pool.size(), TLS)}); + return IterBool.first->second.Number; +} + +unsigned AddressPool::getIndex(SymbolWithOffset SymWithOffs, bool TLS) { + HasBeenUsed = true; auto IterBool = - Pool.insert(std::make_pair(Sym, AddressPoolEntry(Pool.size(), TLS))); + Pool.insert({SymWithOffs, AddressPoolEntry(Pool.size(), TLS)}); return IterBool.first->second.Number; } @@ -63,11 +70,21 @@ // Order the address pool entries by ID SmallVector Entries(Pool.size()); - for (const auto &I : Pool) - Entries[I.second.Number] = + for (const auto &I : Pool) { + auto &Entry = Entries[I.second.Number] = I.second.TLS - ? Asm.getObjFileLowering().getDebugThreadLocalSymbol(I.first) - : MCSymbolRefExpr::create(I.first, Asm.OutContext); + ? Asm.getObjFileLowering().getDebugThreadLocalSymbol(I.first.Symbol) + : MCSymbolRefExpr::create(I.first.Symbol, Asm.OutContext); + auto Offset = I.first.Offset; + if (!Offset) + continue; + // Create an expression for the addition or subtraction of the offset. + auto Op = Offset < 0 ? MCBinaryExpr::Sub : MCBinaryExpr::Add; + const auto OffsetExpr = + MCConstantExpr::create(std::abs(Offset), Asm.OutContext); + const MCExpr *SymbolExpr = Entry; + Entry = MCBinaryExpr::create(Op, SymbolExpr, OffsetExpr, Asm.OutContext); + } for (const MCExpr *Entry : Entries) Asm.OutStreamer->EmitValue(Entry, Asm.getDataLayout().getPointerSize());