aboutsummaryrefslogtreecommitdiff
path: root/lib/MC/MCELFStreamer.cpp
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2010-09-25 05:42:19 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2010-09-25 05:42:19 +0000
commit73ffea47d20bc9f559b4ce0c60166ee504073832 (patch)
treee87577519219fb1ad03bd11f9a15521e65cc5777 /lib/MC/MCELFStreamer.cpp
parentb0ba0f4170dcfe1dbce17680c16cffce311e3ad8 (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.cpp61
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,