aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/MC/MCSection.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-17 08:49:25 -0800
commit4272372c571cd33edc77a8844b0a224ad7339138 (patch)
tree453e49b1991053162fa1d33ae8229b14ebd34638 /llvm/lib/MC/MCSection.cpp
parentad622af07990ed0d332513cf2244b4c45b476ac7 (diff)
downloadllvm-4272372c571cd33edc77a8844b0a224ad7339138.zip
llvm-4272372c571cd33edc77a8844b0a224ad7339138.tar.gz
llvm-4272372c571cd33edc77a8844b0a224ad7339138.tar.bz2
[ MC ] Match labels to existing fragments even when switching sections.
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/MCSection.cpp')
-rw-r--r--llvm/lib/MC/MCSection.cpp35
1 files changed, 35 insertions, 0 deletions
diff --git a/llvm/lib/MC/MCSection.cpp b/llvm/lib/MC/MCSection.cpp
index 2c892ab..7a95305 100644
--- a/llvm/lib/MC/MCSection.cpp
+++ b/llvm/lib/MC/MCSection.cpp
@@ -86,6 +86,41 @@ MCSection::getSubsectionInsertionPoint(unsigned Subsection) {
return IP;
}
+void MCSection::addPendingLabel(MCSymbol* label, unsigned Subsection) {
+ PendingLabels.push_back(PendingLabel(label, Subsection));
+}
+
+void MCSection::flushPendingLabels(MCFragment *F, uint64_t FOffset,
+ unsigned Subsection) {
+ if (PendingLabels.empty())
+ return;
+
+ // Set the fragment and fragment offset for all pending symbols in the
+ // specified Subsection, and remove those symbols from the pending list.
+ for (auto It = PendingLabels.begin(); It != PendingLabels.end(); ++It) {
+ PendingLabel& Label = *It;
+ if (Label.Subsection == Subsection) {
+ Label.Sym->setFragment(F);
+ Label.Sym->setOffset(FOffset);
+ PendingLabels.erase(It--);
+ }
+ }
+}
+
+void MCSection::flushPendingLabels() {
+ // Make sure all remaining pending labels point to data fragments, by
+ // creating new empty data fragments for each Subsection with labels pending.
+ while (!PendingLabels.empty()) {
+ PendingLabel& Label = PendingLabels[0];
+ iterator CurInsertionPoint =
+ this->getSubsectionInsertionPoint(Label.Subsection);
+ MCFragment *F = new MCDataFragment();
+ getFragmentList().insert(CurInsertionPoint, F);
+ F->setParent(this);
+ flushPendingLabels(F, 0, Label.Subsection);
+ }
+}
+
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void MCSection::dump() const {
raw_ostream &OS = errs();