diff options
author | Rafael Espindola <rafael.espindola@gmail.com> | 2010-09-25 05:42:19 +0000 |
---|---|---|
committer | Rafael Espindola <rafael.espindola@gmail.com> | 2010-09-25 05:42:19 +0000 |
commit | 73ffea47d20bc9f559b4ce0c60166ee504073832 (patch) | |
tree | e87577519219fb1ad03bd11f9a15521e65cc5777 /lib/MC/MCELFStreamer.cpp | |
parent | b0ba0f4170dcfe1dbce17680c16cffce311e3ad8 (diff) |
Move ELF to HasReliableSymbolDifference=true. Also take the opportunity to put
symbols defined in merge sections in independent atoms.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@114786 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/MC/MCELFStreamer.cpp')
-rw-r--r-- | lib/MC/MCELFStreamer.cpp | 61 |
1 files changed, 57 insertions, 4 deletions
diff --git a/lib/MC/MCELFStreamer.cpp b/lib/MC/MCELFStreamer.cpp index 5dc5ab08da..6bf61a194c 100644 --- a/lib/MC/MCELFStreamer.cpp +++ b/lib/MC/MCELFStreamer.cpp @@ -149,20 +149,43 @@ void MCELFStreamer::InitSections() { SetSectionText(); } +static bool isSymbolLinkerVisible(const MCAssembler &Asm, + const MCSymbolData &Data) { + const MCSymbol &Symbol = Data.getSymbol(); + // Absolute temporary labels are never visible. + if (!Symbol.isInSection()) + return false; + + if (Asm.getBackend().doesSectionRequireSymbols(Symbol.getSection())) + return true; + + if (!Data.isExternal()) + return false; + + return Asm.isSymbolLinkerVisible(Symbol); +} + void MCELFStreamer::EmitLabel(MCSymbol *Symbol) { assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); + Symbol->setSection(*CurSection); + + MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); + + // We have to create a new fragment if this is an atom defining symbol, + // fragments cannot span atoms. + if (isSymbolLinkerVisible(getAssembler(), SD)) + new MCDataFragment(getCurrentSectionData()); + // FIXME: This is wasteful, we don't necessarily need to create a data // fragment. Instead, we should mark the symbol as pointing into the data // fragment if it exists, otherwise we should just queue the label and set its // fragment pointer when we emit the next fragment. MCDataFragment *F = getOrCreateDataFragment(); - MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); + assert(!SD.getFragment() && "Unexpected fragment on symbol data!"); SD.setFragment(F); SD.setOffset(F->getContents().size()); - - Symbol->setSection(*CurSection); } void MCELFStreamer::EmitAssemblerFlag(MCAssemblerFlag Flag) { @@ -476,7 +499,37 @@ void MCELFStreamer::EmitInstruction(const MCInst &Inst) { } void MCELFStreamer::Finish() { - getAssembler().Finish(); + // FIXME: We create more atoms than it is necessary. Some relocations to + // merge sections can be implemented with section address + offset, + // figure out which ones and why. + + // First, scan the symbol table to build a lookup table from fragments to + // defining symbols. + DenseMap<const MCFragment*, MCSymbolData*> DefiningSymbolMap; + for (MCAssembler::symbol_iterator it = getAssembler().symbol_begin(), + ie = getAssembler().symbol_end(); it != ie; ++it) { + if (isSymbolLinkerVisible(getAssembler(), *it) && + it->getFragment()) { + // An atom defining symbol should never be internal to a fragment. + assert(it->getOffset() == 0 && "Invalid offset in atom defining symbol!"); + DefiningSymbolMap[it->getFragment()] = it; + } + } + + // Set the fragment atom associations by tracking the last seen atom defining + // symbol. + for (MCAssembler::iterator it = getAssembler().begin(), + ie = getAssembler().end(); it != ie; ++it) { + MCSymbolData *CurrentAtom = 0; + for (MCSectionData::iterator it2 = it->begin(), + ie2 = it->end(); it2 != ie2; ++it2) { + if (MCSymbolData *SD = DefiningSymbolMap.lookup(it2)) + CurrentAtom = SD; + it2->setAtom(CurrentAtom); + } + } + + this->MCObjectStreamer::Finish(); } MCStreamer *llvm::createELFStreamer(MCContext &Context, TargetAsmBackend &TAB, |