diff options
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, |