aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/MC/MCObjectStreamer.cpp
diff options
context:
space:
mode:
authorDerek Schuff <dschuff@google.com>2014-10-22 22:38:06 +0000
committerDerek Schuff <dschuff@google.com>2014-10-22 22:38:06 +0000
commit5f708e5ec8f0540a892a9c24c9d569681cc3b30a (patch)
treed065d9c02312a4c8b1a6d1ba6dc41fe630c46f76 /llvm/lib/MC/MCObjectStreamer.cpp
parent2809b98c0e80ff3b98df2f15eb87d2efe7a2edfe (diff)
downloadllvm-5f708e5ec8f0540a892a9c24c9d569681cc3b30a.zip
llvm-5f708e5ec8f0540a892a9c24c9d569681cc3b30a.tar.gz
llvm-5f708e5ec8f0540a892a9c24c9d569681cc3b30a.tar.bz2
[MC] Attach labels to existing fragments instead of using a separate fragment
Summary: Currently when emitting a label, a new data fragment is created for it if the current fragment isn't a data fragment. This change instead enqueues the label and attaches it to the next fragment (e.g. created for the next instruction) if possible. When bundle alignment is not enabled, this has no functionality change (it just results in fewer extra fragments being created). For bundle alignment, previously labels would point to the beginning of the bundle padding instead of the beginning of the emitted instruction. This was not only less efficient (e.g. jumping to the nops instead of past them) but also led to miscalculation of the address of the GOT (since MC uses a label difference rather than emitting a "." symbol). Fixes https://code.google.com/p/nativeclient/issues/detail?id=3982 Test Plan: regression test attached Reviewers: jvoung, eliben Subscribers: jfb, llvm-commits Differential Revision: http://reviews.llvm.org/D5915 llvm-svn: 220439
Diffstat (limited to 'llvm/lib/MC/MCObjectStreamer.cpp')
-rw-r--r--llvm/lib/MC/MCObjectStreamer.cpp38
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();
}