[MC] Factor MCObjectStreamer::addFragmentAtoms out of MachO streamer.

This code previously existed only in MCMachOStreamer but is
useful for WebAssembly too.  See: D46335

Differential Revision: https://reviews.llvm.org/D46297

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@331412 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Sam Clegg 2018-05-02 23:01:10 +00:00
parent 47a8f72fea
commit 1e2e5ffd56
4 changed files with 32 additions and 24 deletions

View File

@ -85,6 +85,8 @@ protected:
/// will be used as a symbol offset within the fragment.
void flushPendingLabels(MCFragment *F, uint64_t FOffset = 0);
void addFragmentAtoms();
public:
void visitUsedSymbol(const MCSymbol &Sym) override;

View File

@ -455,30 +455,7 @@ void MCMachOStreamer::FinishImpl() {
// We have to set the fragment atom associations so we can relax properly for
// Mach-O.
// First, scan the symbol table to build a lookup table from fragments to
// defining symbols.
DenseMap<const MCFragment *, const MCSymbol *> DefiningSymbolMap;
for (const MCSymbol &Symbol : getAssembler().symbols()) {
if (getAssembler().isSymbolLinkerVisible(Symbol) && Symbol.isInSection() &&
!Symbol.isVariable()) {
// An atom defining symbol should never be internal to a fragment.
assert(Symbol.getOffset() == 0 &&
"Invalid offset in atom defining symbol!");
DefiningSymbolMap[Symbol.getFragment()] = &Symbol;
}
}
// Set the fragment atom associations by tracking the last seen atom defining
// symbol.
for (MCSection &Sec : getAssembler()) {
const MCSymbol *CurrentAtom = nullptr;
for (MCFragment &Frag : Sec) {
if (const MCSymbol *Symbol = DefiningSymbolMap.lookup(&Frag))
CurrentAtom = Symbol;
Frag.setAtom(CurrentAtom);
}
}
addFragmentAtoms();
this->MCObjectStreamer::FinishImpl();
}

View File

@ -60,6 +60,32 @@ void MCObjectStreamer::flushPendingLabels(MCFragment *F, uint64_t FOffset) {
PendingLabels.clear();
}
void MCObjectStreamer::addFragmentAtoms() {
// First, scan the symbol table to build a lookup table from fragments to
// defining symbols.
DenseMap<const MCFragment *, const MCSymbol *> DefiningSymbolMap;
for (const MCSymbol &Symbol : getAssembler().symbols()) {
if (getAssembler().isSymbolLinkerVisible(Symbol) && Symbol.isInSection() &&
!Symbol.isVariable()) {
// An atom defining symbol should never be internal to a fragment.
assert(Symbol.getOffset() == 0 &&
"Invalid offset in atom defining symbol!");
DefiningSymbolMap[Symbol.getFragment()] = &Symbol;
}
}
// Set the fragment atom associations by tracking the last seen atom defining
// symbol.
for (MCSection &Sec : getAssembler()) {
const MCSymbol *CurrentAtom = nullptr;
for (MCFragment &Frag : Sec) {
if (const MCSymbol *Symbol = DefiningSymbolMap.lookup(&Frag))
CurrentAtom = Symbol;
Frag.setAtom(CurrentAtom);
}
}
}
// As a compile-time optimization, avoid allocating and evaluating an MCExpr
// tree for (Hi - Lo) when Hi and Lo are offsets into the same fragment.
static Optional<uint64_t> absoluteSymbolDiff(const MCSymbol *Hi,

View File

@ -198,6 +198,9 @@ void MCWasmStreamer::EmitInstToData(const MCInst &Inst,
void MCWasmStreamer::FinishImpl() {
EmitFrames(nullptr);
// Set fragment atoms so we can map from code fragment to defining symbol
addFragmentAtoms();
this->MCObjectStreamer::FinishImpl();
}