summaryrefslogtreecommitdiffstats
path: root/llvm/lib/MC/MCObjectStreamer.cpp
diff options
context:
space:
mode:
authorMichael Trent <mtrent@apple.com>2019-12-11 10:42:37 -0800
committerMichael Trent <mtrent@apple.com>2019-12-18 09:55:54 -0800
commit6f95d33e2b9e561e025f63b7a179b6e495f62c51 (patch)
treeb65d033bed8e4a65ce3d42bd81d02991503acfd2 /llvm/lib/MC/MCObjectStreamer.cpp
parentb99111b3e4ab6e71bab6b4ba01de29be9dc5b0f8 (diff)
downloadbcm5719-llvm-6f95d33e2b9e561e025f63b7a179b6e495f62c51.tar.gz
bcm5719-llvm-6f95d33e2b9e561e025f63b7a179b6e495f62c51.zip
[ MC ] Match labels to existing fragments even when switching sections.
(This commit restores the original branch (4272372c571) and applies an additional change dropped from the original in a bad merge. This change should address the previous bot failures. Both changes reviewed by pete.) Summary: This commit builds upon Derek Schuff's 2014 commit for attaching labels to existing fragments ( Diff Revision: http://reviews.llvm.org/D5915 ) When temporary labels appear ahead of a fragment, MCObjectStreamer will track the temporary label symbol in a "Pending Labels" list. Labels are associated with fragments when a real fragment arrives; otherwise, an empty data fragment will be created if the streamer's section changes or if the stream finishes. This commit moves the "Pending Labels" list into each MCStream, so that this label-fragment matching process is resilient to section changes. If the streamer emits a label in a new section, switches to another section to do other work, then switches back to the first section and emits a fragment, that initial label will be associated with this new fragment. Labels will only receive empty data fragments in the case where no other fragment exists for that section. The downstream effects of this can be seen in Mach-O relocations. The previous approach could produce local section relocations and external symbol relocations for the same data in an object file, and this mix of relocation types resulted in problems in the ld64 Mach-O linker. This commit ensures relocations triggered by temporary labels are consistent. Reviewers: pete, ab, dschuff Reviewed By: pete, dschuff Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D71368
Diffstat (limited to 'llvm/lib/MC/MCObjectStreamer.cpp')
-rw-r--r--llvm/lib/MC/MCObjectStreamer.cpp75
1 files changed, 61 insertions, 14 deletions
diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp
index 6c85f2296cf..1ed6ec1015b 100644
--- a/llvm/lib/MC/MCObjectStreamer.cpp
+++ b/llvm/lib/MC/MCObjectStreamer.cpp
@@ -42,20 +42,64 @@ MCAssembler *MCObjectStreamer::getAssemblerPtr() {
return nullptr;
}
+void MCObjectStreamer::addPendingLabel(MCSymbol* S) {
+ MCSection *CurSection = getCurrentSectionOnly();
+ if (CurSection) {
+ // Register labels that have not yet been assigned to a Section.
+ if (!PendingLabels.empty()) {
+ for (MCSymbol* Sym : PendingLabels)
+ CurSection->addPendingLabel(Sym);
+ PendingLabels.clear();
+ }
+
+ // Add this label to the current Section / Subsection.
+ CurSection->addPendingLabel(S, CurSubsectionIdx);
+
+ // Add this Section to the list of PendingLabelSections.
+ auto SecIt = std::find(PendingLabelSections.begin(),
+ PendingLabelSections.end(), CurSection);
+ if (SecIt == PendingLabelSections.end())
+ PendingLabelSections.push_back(CurSection);
+ }
+ else
+ // There is no Section / Subsection for this label yet.
+ PendingLabels.push_back(S);
+}
+
void MCObjectStreamer::flushPendingLabels(MCFragment *F, uint64_t FOffset) {
- if (PendingLabels.empty())
+ MCSection *CurSection = getCurrentSectionOnly();
+ if (!CurSection) {
+ assert(PendingLabels.empty());
return;
- if (!F) {
- F = new MCDataFragment();
- MCSection *CurSection = getCurrentSectionOnly();
- CurSection->getFragmentList().insert(CurInsertionPoint, F);
- F->setParent(CurSection);
}
- for (MCSymbol *Sym : PendingLabels) {
- Sym->setFragment(F);
- Sym->setOffset(FOffset);
+ // Register labels that have not yet been assigned to a Section.
+ if (!PendingLabels.empty()) {
+ for (MCSymbol* Sym : PendingLabels)
+ CurSection->addPendingLabel(Sym, CurSubsectionIdx);
+ PendingLabels.clear();
}
- PendingLabels.clear();
+
+ // Associate a fragment with this label, either the supplied fragment
+ // or an empty data fragment.
+ if (F)
+ CurSection->flushPendingLabels(F, FOffset, CurSubsectionIdx);
+ else
+ CurSection->flushPendingLabels(nullptr, 0, CurSubsectionIdx);
+}
+
+void MCObjectStreamer::flushPendingLabels() {
+ // Register labels that have not yet been assigned to a Section.
+ if (!PendingLabels.empty()) {
+ MCSection *CurSection = getCurrentSectionOnly();
+ assert(CurSection);
+ for (MCSymbol* Sym : PendingLabels)
+ CurSection->addPendingLabel(Sym, CurSubsectionIdx);
+ PendingLabels.clear();
+ }
+
+ // Assign an empty data fragment to all remaining pending labels.
+ for (MCSection* Section : PendingLabelSections)
+ Section->flushPendingLabels();
}
// When fixup's offset is a forward declared label, e.g.:
@@ -120,6 +164,7 @@ void MCObjectStreamer::reset() {
EmitEHFrame = true;
EmitDebugFrame = false;
PendingLabels.clear();
+ PendingLabelSections.clear();
MCStreamer::reset();
}
@@ -237,7 +282,7 @@ void MCObjectStreamer::EmitLabel(MCSymbol *Symbol, SMLoc Loc) {
// fragment. (They will all be reassigned to a real fragment in
// flushPendingLabels())
Symbol->setOffset(0);
- PendingLabels.push_back(Symbol);
+ addPendingLabel(Symbol);
}
}
@@ -257,7 +302,7 @@ void MCObjectStreamer::EmitLabelAtPos(MCSymbol *Symbol, SMLoc Loc,
assert(isa<MCDummyFragment>(F) &&
"F must either be an MCDataFragment or the pending MCDummyFragment");
assert(Offset == 0);
- PendingLabels.push_back(Symbol);
+ addPendingLabel(Symbol);
}
}
@@ -292,7 +337,6 @@ void MCObjectStreamer::ChangeSection(MCSection *Section,
bool MCObjectStreamer::changeSectionImpl(MCSection *Section,
const MCExpr *Subsection) {
assert(Section && "Cannot switch to a null section!");
- flushPendingLabels(nullptr);
getContext().clearDwarfLocSeen();
bool Created = getAssembler().registerSection(*Section);
@@ -303,8 +347,9 @@ bool MCObjectStreamer::changeSectionImpl(MCSection *Section,
report_fatal_error("Cannot evaluate subsection number");
if (IntSubsection < 0 || IntSubsection > 8192)
report_fatal_error("Subsection number out of range");
+ CurSubsectionIdx = unsigned(IntSubsection);
CurInsertionPoint =
- Section->getSubsectionInsertionPoint(unsigned(IntSubsection));
+ Section->getSubsectionInsertionPoint(CurSubsectionIdx);
return Created;
}
@@ -712,7 +757,9 @@ void MCObjectStreamer::FinishImpl() {
// Dump out the dwarf file & directory tables and line tables.
MCDwarfLineTable::Emit(this, getAssembler().getDWARFLinetableParams());
+ // Update any remaining pending labels with empty data fragments.
flushPendingLabels();
+
resolvePendingFixups();
getAssembler().Finish();
}
OpenPOWER on IntegriCloud