aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/MC/MCAssembler.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/MC/MCAssembler.cpp')
-rw-r--r--llvm/lib/MC/MCAssembler.cpp77
1 files changed, 40 insertions, 37 deletions
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp
index e731dfc..a8652d2 100644
--- a/llvm/lib/MC/MCAssembler.cpp
+++ b/llvm/lib/MC/MCAssembler.cpp
@@ -438,28 +438,6 @@ void MCAssembler::layoutBundle(MCFragment *Prev, MCFragment *F) const {
DF->Offset = EF->Offset;
}
-void MCAssembler::ensureValid(MCSection &Sec) const {
- if (Sec.hasLayout())
- return;
- Sec.setHasLayout(true);
- MCFragment *Prev = nullptr;
- uint64_t Offset = 0;
- for (MCFragment &F : Sec) {
- F.Offset = Offset;
- if (isBundlingEnabled() && F.hasInstructions()) {
- layoutBundle(Prev, &F);
- Offset = F.Offset;
- }
- Offset += computeFragmentSize(F);
- Prev = &F;
- }
-}
-
-uint64_t MCAssembler::getFragmentOffset(const MCFragment &F) const {
- ensureValid(*F.getParent());
- return F.Offset;
-}
-
// Simple getSymbolOffset helper for the non-variable case.
static bool getLabelOffset(const MCAssembler &Asm, const MCSymbol &S,
bool ReportError, uint64_t &Val) {
@@ -944,22 +922,20 @@ void MCAssembler::layout() {
// Layout until everything fits.
this->HasLayout = true;
+ for (MCSection &Sec : *this)
+ layoutSection(Sec);
while (layoutOnce()) {
- if (getContext().hadError())
- return;
- // Size of fragments in one section can depend on the size of fragments in
- // another. If any fragment has changed size, we have to re-layout (and
- // as a result possibly further relax) all.
- for (MCSection &Sec : *this)
- Sec.setHasLayout(false);
}
DEBUG_WITH_TYPE("mc-dump", {
errs() << "assembler backend - post-relaxation\n--\n";
dump(); });
- // Finalize the layout, including fragment lowering.
- getBackend().finishLayout(*this);
+ // Some targets might want to adjust fragment offsets. If so, perform another
+ // layout loop.
+ if (getBackend().finishLayout(*this))
+ for (MCSection &Sec : *this)
+ layoutSection(Sec);
DEBUG_WITH_TYPE("mc-dump", {
errs() << "assembler backend - final-layout\n--\n";
@@ -1312,15 +1288,42 @@ bool MCAssembler::relaxFragment(MCFragment &F) {
}
}
+void MCAssembler::layoutSection(MCSection &Sec) {
+ MCFragment *Prev = nullptr;
+ uint64_t Offset = 0;
+ for (MCFragment &F : Sec) {
+ F.Offset = Offset;
+ if (LLVM_UNLIKELY(isBundlingEnabled())) {
+ if (F.hasInstructions()) {
+ layoutBundle(Prev, &F);
+ Offset = F.Offset;
+ }
+ Prev = &F;
+ }
+ Offset += computeFragmentSize(F);
+ }
+}
+
bool MCAssembler::layoutOnce() {
++stats::RelaxationSteps;
- bool Changed = false;
- for (MCSection &Sec : *this)
- for (MCFragment &Frag : Sec)
- if (relaxFragment(Frag))
- Changed = true;
- return Changed;
+ // Size of fragments in one section can depend on the size of fragments in
+ // another. If any fragment has changed size, we have to re-layout (and
+ // as a result possibly further relax) all.
+ bool ChangedAny = false;
+ for (MCSection &Sec : *this) {
+ for (;;) {
+ bool Changed = false;
+ for (MCFragment &F : Sec)
+ if (relaxFragment(F))
+ Changed = true;
+ ChangedAny |= Changed;
+ if (!Changed)
+ break;
+ layoutSection(Sec);
+ }
+ }
+ return ChangedAny;
}
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)