diff options
Diffstat (limited to 'llvm/lib/MC/MCObjectStreamer.cpp')
-rw-r--r-- | llvm/lib/MC/MCObjectStreamer.cpp | 38 |
1 files changed, 29 insertions, 9 deletions
diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index a478899..e6f50b0 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -42,6 +42,21 @@ MCObjectStreamer::~MCObjectStreamer() { delete Assembler; } +void MCObjectStreamer::flushPendingLabels(MCFragment *F) { + if (PendingLabels.size()) { + if (!F) { + F = new MCDataFragment(); + CurSectionData->getFragmentList().insert(CurInsertionPoint, F); + F->setParent(CurSectionData); + } + for (MCSymbolData *SD : PendingLabels) { + SD->setFragment(F); + SD->setOffset(0); + } + PendingLabels.clear(); + } +} + void MCObjectStreamer::reset() { if (Assembler) Assembler->reset(); @@ -49,6 +64,7 @@ void MCObjectStreamer::reset() { CurInsertionPoint = MCSectionData::iterator(); EmitEHFrame = true; EmitDebugFrame = false; + PendingLabels.clear(); MCStreamer::reset(); } @@ -72,7 +88,7 @@ MCFragment *MCObjectStreamer::getCurrentFragment() const { return nullptr; } -MCDataFragment *MCObjectStreamer::getOrCreateDataFragment() const { +MCDataFragment *MCObjectStreamer::getOrCreateDataFragment() { MCDataFragment *F = dyn_cast_or_null<MCDataFragment>(getCurrentFragment()); // When bundling is enabled, we don't want to add data to a fragment that // already has instructions (see MCELFStreamer::EmitInstToData for details) @@ -127,15 +143,17 @@ void MCObjectStreamer::EmitLabel(MCSymbol *Symbol) { MCStreamer::EmitLabel(Symbol); MCSymbolData &SD = getAssembler().getOrCreateSymbolData(*Symbol); - - // 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(); assert(!SD.getFragment() && "Unexpected fragment on symbol data!"); - SD.setFragment(F); - SD.setOffset(F->getContents().size()); + + // If there is a current fragment, mark the symbol as pointing into it. + // Otherwise queue the label and set its fragment pointer when we emit the + // next fragment. + if (dyn_cast_or_null<MCDataFragment>(getCurrentFragment())) { + SD.setFragment(F); + SD.setOffset(F->getContents().size()); + } else { + PendingLabels.push_back(&SD); + } } void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value) { @@ -164,6 +182,7 @@ void MCObjectStreamer::EmitWeakReference(MCSymbol *Alias, void MCObjectStreamer::ChangeSection(const MCSection *Section, const MCExpr *Subsection) { assert(Section && "Cannot switch to a null section!"); + flushPendingLabels(nullptr); CurSectionData = &getAssembler().getOrCreateSectionData(*Section); @@ -398,5 +417,6 @@ void MCObjectStreamer::FinishImpl() { // Dump out the dwarf file & directory tables and line tables. MCDwarfLineTable::Emit(this); + flushPendingLabels(nullptr); getAssembler().Finish(); } |