Skip to content

Commit 03ae9f9

Browse files
MaskRaytru
authored andcommitted
Revert "[MC] Compute fragment offsets eagerly"
This reverts commit 1a47f3f. Fix llvm#100283 This commit is actually a trigger of other preexisting problems: * Size change of fill fragments does not influence the fixed-point iteration. * The `invalid number of bytes` error is reported too early. Since `.zero A-B` might have temporary negative values in the first few iterations. However, the problems appeared at least "benign" (did not affect the Linux kernel builds) before this commit. (cherry picked from commit 4eb5450)
1 parent 742576d commit 03ae9f9

File tree

7 files changed

+71
-54
lines changed

7 files changed

+71
-54
lines changed

llvm/include/llvm/MC/MCAsmBackend.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -217,9 +217,8 @@ class MCAsmBackend {
217217
virtual bool writeNopData(raw_ostream &OS, uint64_t Count,
218218
const MCSubtargetInfo *STI) const = 0;
219219

220-
// Return true if fragment offsets have been adjusted and an extra layout
221-
// iteration is needed.
222-
virtual bool finishLayout(const MCAssembler &Asm) const { return false; }
220+
/// Give backend an opportunity to finish layout after relaxation
221+
virtual void finishLayout(MCAssembler const &Asm) const {}
223222

224223
/// Handle any target-specific assembler flags. By default, do nothing.
225224
virtual void handleAssemblerFlag(MCAssemblerFlag Flag) {}

llvm/include/llvm/MC/MCAssembler.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,6 @@ class MCAssembler {
111111
/// Check whether the given fragment needs relaxation.
112112
bool fragmentNeedsRelaxation(const MCRelaxableFragment *IF) const;
113113

114-
void layoutSection(MCSection &Sec);
115114
/// Perform one layout iteration and return true if any offsets
116115
/// were adjusted.
117116
bool layoutOnce();
@@ -148,9 +147,10 @@ class MCAssembler {
148147
uint64_t computeFragmentSize(const MCFragment &F) const;
149148

150149
void layoutBundle(MCFragment *Prev, MCFragment *F) const;
150+
void ensureValid(MCSection &Sec) const;
151151

152152
// Get the offset of the given fragment inside its containing section.
153-
uint64_t getFragmentOffset(const MCFragment &F) const { return F.Offset; }
153+
uint64_t getFragmentOffset(const MCFragment &F) const;
154154

155155
uint64_t getSectionAddressSize(const MCSection &Sec) const;
156156
uint64_t getSectionFileSize(const MCSection &Sec) const;

llvm/include/llvm/MC/MCSection.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ class MCSection {
9999
/// Whether this section has had instructions emitted into it.
100100
bool HasInstructions : 1;
101101

102+
bool HasLayout : 1;
103+
102104
bool IsRegistered : 1;
103105

104106
bool IsText : 1;
@@ -167,6 +169,9 @@ class MCSection {
167169
bool hasInstructions() const { return HasInstructions; }
168170
void setHasInstructions(bool Value) { HasInstructions = Value; }
169171

172+
bool hasLayout() const { return HasLayout; }
173+
void setHasLayout(bool Value) { HasLayout = Value; }
174+
170175
bool isRegistered() const { return IsRegistered; }
171176
void setIsRegistered(bool Value) { IsRegistered = Value; }
172177

llvm/lib/MC/MCAssembler.cpp

Lines changed: 37 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,28 @@ void MCAssembler::layoutBundle(MCFragment *Prev, MCFragment *F) const {
432432
DF->Offset = EF->Offset;
433433
}
434434

435+
void MCAssembler::ensureValid(MCSection &Sec) const {
436+
if (Sec.hasLayout())
437+
return;
438+
Sec.setHasLayout(true);
439+
MCFragment *Prev = nullptr;
440+
uint64_t Offset = 0;
441+
for (MCFragment &F : Sec) {
442+
F.Offset = Offset;
443+
if (isBundlingEnabled() && F.hasInstructions()) {
444+
layoutBundle(Prev, &F);
445+
Offset = F.Offset;
446+
}
447+
Offset += computeFragmentSize(F);
448+
Prev = &F;
449+
}
450+
}
451+
452+
uint64_t MCAssembler::getFragmentOffset(const MCFragment &F) const {
453+
ensureValid(*F.getParent());
454+
return F.Offset;
455+
}
456+
435457
// Simple getSymbolOffset helper for the non-variable case.
436458
static bool getLabelOffset(const MCAssembler &Asm, const MCSymbol &S,
437459
bool ReportError, uint64_t &Val) {
@@ -916,20 +938,22 @@ void MCAssembler::layout() {
916938

917939
// Layout until everything fits.
918940
this->HasLayout = true;
919-
for (MCSection &Sec : *this)
920-
layoutSection(Sec);
921941
while (layoutOnce()) {
942+
if (getContext().hadError())
943+
return;
944+
// Size of fragments in one section can depend on the size of fragments in
945+
// another. If any fragment has changed size, we have to re-layout (and
946+
// as a result possibly further relax) all.
947+
for (MCSection &Sec : *this)
948+
Sec.setHasLayout(false);
922949
}
923950

924951
DEBUG_WITH_TYPE("mc-dump", {
925952
errs() << "assembler backend - post-relaxation\n--\n";
926953
dump(); });
927954

928-
// Some targets might want to adjust fragment offsets. If so, perform another
929-
// layout loop.
930-
if (getBackend().finishLayout(*this))
931-
for (MCSection &Sec : *this)
932-
layoutSection(Sec);
955+
// Finalize the layout, including fragment lowering.
956+
getBackend().finishLayout(*this);
933957

934958
DEBUG_WITH_TYPE("mc-dump", {
935959
errs() << "assembler backend - final-layout\n--\n";
@@ -1282,42 +1306,15 @@ bool MCAssembler::relaxFragment(MCFragment &F) {
12821306
}
12831307
}
12841308

1285-
void MCAssembler::layoutSection(MCSection &Sec) {
1286-
MCFragment *Prev = nullptr;
1287-
uint64_t Offset = 0;
1288-
for (MCFragment &F : Sec) {
1289-
F.Offset = Offset;
1290-
if (LLVM_UNLIKELY(isBundlingEnabled())) {
1291-
if (F.hasInstructions()) {
1292-
layoutBundle(Prev, &F);
1293-
Offset = F.Offset;
1294-
}
1295-
Prev = &F;
1296-
}
1297-
Offset += computeFragmentSize(F);
1298-
}
1299-
}
1300-
13011309
bool MCAssembler::layoutOnce() {
13021310
++stats::RelaxationSteps;
13031311

1304-
// Size of fragments in one section can depend on the size of fragments in
1305-
// another. If any fragment has changed size, we have to re-layout (and
1306-
// as a result possibly further relax) all.
1307-
bool ChangedAny = false;
1308-
for (MCSection &Sec : *this) {
1309-
for (;;) {
1310-
bool Changed = false;
1311-
for (MCFragment &F : Sec)
1312-
if (relaxFragment(F))
1313-
Changed = true;
1314-
ChangedAny |= Changed;
1315-
if (!Changed)
1316-
break;
1317-
layoutSection(Sec);
1318-
}
1319-
}
1320-
return ChangedAny;
1312+
bool Changed = false;
1313+
for (MCSection &Sec : *this)
1314+
for (MCFragment &Frag : Sec)
1315+
if (relaxFragment(Frag))
1316+
Changed = true;
1317+
return Changed;
13211318
}
13221319

13231320
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)

llvm/lib/MC/MCSection.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,8 @@ using namespace llvm;
2323
MCSection::MCSection(SectionVariant V, StringRef Name, bool IsText,
2424
bool IsVirtual, MCSymbol *Begin)
2525
: Begin(Begin), BundleGroupBeforeFirstInst(false), HasInstructions(false),
26-
IsRegistered(false), IsText(IsText), IsVirtual(IsVirtual), Name(Name),
27-
Variant(V) {
26+
HasLayout(false), IsRegistered(false), IsText(IsText),
27+
IsVirtual(IsVirtual), Name(Name), Variant(V) {
2828
DummyFragment.setParent(this);
2929
// The initial subsection number is 0. Create a fragment list.
3030
CurFragList = &Subsections.emplace_back(0u, FragList{}).second;

llvm/lib/Target/Hexagon/MCTargetDesc/HexagonAsmBackend.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -702,7 +702,7 @@ class HexagonAsmBackend : public MCAsmBackend {
702702
return true;
703703
}
704704

705-
bool finishLayout(const MCAssembler &Asm) const override {
705+
void finishLayout(MCAssembler const &Asm) const override {
706706
SmallVector<MCFragment *> Frags;
707707
for (MCSection &Sec : Asm) {
708708
Frags.clear();
@@ -747,6 +747,7 @@ class HexagonAsmBackend : public MCAsmBackend {
747747
//assert(!Error);
748748
(void)Error;
749749
ReplaceInstruction(Asm.getEmitter(), RF, Inst);
750+
Sec.setHasLayout(false);
750751
Size = 0; // Only look back one instruction
751752
break;
752753
}
@@ -756,7 +757,6 @@ class HexagonAsmBackend : public MCAsmBackend {
756757
}
757758
}
758759
}
759-
return true;
760760
}
761761
}; // class HexagonAsmBackend
762762

llvm/lib/Target/X86/MCTargetDesc/X86AsmBackend.cpp

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ class X86AsmBackend : public MCAsmBackend {
201201
bool padInstructionEncoding(MCRelaxableFragment &RF, MCCodeEmitter &Emitter,
202202
unsigned &RemainingSize) const;
203203

204-
bool finishLayout(const MCAssembler &Asm) const override;
204+
void finishLayout(const MCAssembler &Asm) const override;
205205

206206
unsigned getMaximumNopSize(const MCSubtargetInfo &STI) const override;
207207

@@ -856,15 +856,15 @@ bool X86AsmBackend::padInstructionEncoding(MCRelaxableFragment &RF,
856856
return Changed;
857857
}
858858

859-
bool X86AsmBackend::finishLayout(const MCAssembler &Asm) const {
859+
void X86AsmBackend::finishLayout(MCAssembler const &Asm) const {
860860
// See if we can further relax some instructions to cut down on the number of
861861
// nop bytes required for code alignment. The actual win is in reducing
862862
// instruction count, not number of bytes. Modern X86-64 can easily end up
863863
// decode limited. It is often better to reduce the number of instructions
864864
// (i.e. eliminate nops) even at the cost of increasing the size and
865865
// complexity of others.
866866
if (!X86PadForAlign && !X86PadForBranchAlign)
867-
return false;
867+
return;
868868

869869
// The processed regions are delimitered by LabeledFragments. -g may have more
870870
// MCSymbols and therefore different relaxation results. X86PadForAlign is
@@ -911,6 +911,9 @@ bool X86AsmBackend::finishLayout(const MCAssembler &Asm) const {
911911
continue;
912912
}
913913

914+
#ifndef NDEBUG
915+
const uint64_t OrigOffset = Asm.getFragmentOffset(F);
916+
#endif
914917
const uint64_t OrigSize = Asm.computeFragmentSize(F);
915918

916919
// To keep the effects local, prefer to relax instructions closest to
@@ -923,7 +926,8 @@ bool X86AsmBackend::finishLayout(const MCAssembler &Asm) const {
923926
// Give the backend a chance to play any tricks it wishes to increase
924927
// the encoding size of the given instruction. Target independent code
925928
// will try further relaxation, but target's may play further tricks.
926-
padInstructionEncoding(RF, Asm.getEmitter(), RemainingSize);
929+
if (padInstructionEncoding(RF, Asm.getEmitter(), RemainingSize))
930+
Sec.setHasLayout(false);
927931

928932
// If we have an instruction which hasn't been fully relaxed, we can't
929933
// skip past it and insert bytes before it. Changing its starting
@@ -940,6 +944,14 @@ bool X86AsmBackend::finishLayout(const MCAssembler &Asm) const {
940944
if (F.getKind() == MCFragment::FT_BoundaryAlign)
941945
cast<MCBoundaryAlignFragment>(F).setSize(RemainingSize);
942946

947+
#ifndef NDEBUG
948+
const uint64_t FinalOffset = Asm.getFragmentOffset(F);
949+
const uint64_t FinalSize = Asm.computeFragmentSize(F);
950+
assert(OrigOffset + OrigSize == FinalOffset + FinalSize &&
951+
"can't move start of next fragment!");
952+
assert(FinalSize == RemainingSize && "inconsistent size computation?");
953+
#endif
954+
943955
// If we're looking at a boundary align, make sure we don't try to pad
944956
// its target instructions for some following directive. Doing so would
945957
// break the alignment of the current boundary align.
@@ -953,7 +965,11 @@ bool X86AsmBackend::finishLayout(const MCAssembler &Asm) const {
953965
}
954966
}
955967

956-
return true;
968+
// The layout is done. Mark every fragment as valid.
969+
for (MCSection &Section : Asm) {
970+
Asm.getFragmentOffset(*Section.curFragList()->Tail);
971+
Asm.computeFragmentSize(*Section.curFragList()->Tail);
972+
}
957973
}
958974

959975
unsigned X86AsmBackend::getMaximumNopSize(const MCSubtargetInfo &STI) const {

0 commit comments

Comments
 (0)