Skip to content

Commit 4eb5450

Browse files
committed
Revert "[MC] Compute fragment offsets eagerly"
This reverts commit 1a47f3f. Fix #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.
1 parent 76a15e5 commit 4eb5450

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
@@ -428,6 +428,28 @@ void MCAssembler::layoutBundle(MCFragment *Prev, MCFragment *F) const {
428428
DF->Offset = EF->Offset;
429429
}
430430

431+
void MCAssembler::ensureValid(MCSection &Sec) const {
432+
if (Sec.hasLayout())
433+
return;
434+
Sec.setHasLayout(true);
435+
MCFragment *Prev = nullptr;
436+
uint64_t Offset = 0;
437+
for (MCFragment &F : Sec) {
438+
F.Offset = Offset;
439+
if (isBundlingEnabled() && F.hasInstructions()) {
440+
layoutBundle(Prev, &F);
441+
Offset = F.Offset;
442+
}
443+
Offset += computeFragmentSize(F);
444+
Prev = &F;
445+
}
446+
}
447+
448+
uint64_t MCAssembler::getFragmentOffset(const MCFragment &F) const {
449+
ensureValid(*F.getParent());
450+
return F.Offset;
451+
}
452+
431453
// Simple getSymbolOffset helper for the non-variable case.
432454
static bool getLabelOffset(const MCAssembler &Asm, const MCSymbol &S,
433455
bool ReportError, uint64_t &Val) {
@@ -907,20 +929,22 @@ void MCAssembler::layout() {
907929

908930
// Layout until everything fits.
909931
this->HasLayout = true;
910-
for (MCSection &Sec : *this)
911-
layoutSection(Sec);
912932
while (layoutOnce()) {
933+
if (getContext().hadError())
934+
return;
935+
// Size of fragments in one section can depend on the size of fragments in
936+
// another. If any fragment has changed size, we have to re-layout (and
937+
// as a result possibly further relax) all.
938+
for (MCSection &Sec : *this)
939+
Sec.setHasLayout(false);
913940
}
914941

915942
DEBUG_WITH_TYPE("mc-dump", {
916943
errs() << "assembler backend - post-relaxation\n--\n";
917944
dump(); });
918945

919-
// Some targets might want to adjust fragment offsets. If so, perform another
920-
// layout loop.
921-
if (getBackend().finishLayout(*this))
922-
for (MCSection &Sec : *this)
923-
layoutSection(Sec);
946+
// Finalize the layout, including fragment lowering.
947+
getBackend().finishLayout(*this);
924948

925949
DEBUG_WITH_TYPE("mc-dump", {
926950
errs() << "assembler backend - final-layout\n--\n";
@@ -1273,42 +1297,15 @@ bool MCAssembler::relaxFragment(MCFragment &F) {
12731297
}
12741298
}
12751299

1276-
void MCAssembler::layoutSection(MCSection &Sec) {
1277-
MCFragment *Prev = nullptr;
1278-
uint64_t Offset = 0;
1279-
for (MCFragment &F : Sec) {
1280-
F.Offset = Offset;
1281-
if (LLVM_UNLIKELY(isBundlingEnabled())) {
1282-
if (F.hasInstructions()) {
1283-
layoutBundle(Prev, &F);
1284-
Offset = F.Offset;
1285-
}
1286-
Prev = &F;
1287-
}
1288-
Offset += computeFragmentSize(F);
1289-
}
1290-
}
1291-
12921300
bool MCAssembler::layoutOnce() {
12931301
++stats::RelaxationSteps;
12941302

1295-
// Size of fragments in one section can depend on the size of fragments in
1296-
// another. If any fragment has changed size, we have to re-layout (and
1297-
// as a result possibly further relax) all.
1298-
bool ChangedAny = false;
1299-
for (MCSection &Sec : *this) {
1300-
for (;;) {
1301-
bool Changed = false;
1302-
for (MCFragment &F : Sec)
1303-
if (relaxFragment(F))
1304-
Changed = true;
1305-
ChangedAny |= Changed;
1306-
if (!Changed)
1307-
break;
1308-
layoutSection(Sec);
1309-
}
1310-
}
1311-
return ChangedAny;
1303+
bool Changed = false;
1304+
for (MCSection &Sec : *this)
1305+
for (MCFragment &Frag : Sec)
1306+
if (relaxFragment(Frag))
1307+
Changed = true;
1308+
return Changed;
13121309
}
13131310

13141311
#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

@@ -854,15 +854,15 @@ bool X86AsmBackend::padInstructionEncoding(MCRelaxableFragment &RF,
854854
return Changed;
855855
}
856856

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

867867
// The processed regions are delimitered by LabeledFragments. -g may have more
868868
// MCSymbols and therefore different relaxation results. X86PadForAlign is
@@ -907,6 +907,9 @@ bool X86AsmBackend::finishLayout(const MCAssembler &Asm) const {
907907
continue;
908908
}
909909

910+
#ifndef NDEBUG
911+
const uint64_t OrigOffset = Asm.getFragmentOffset(F);
912+
#endif
910913
const uint64_t OrigSize = Asm.computeFragmentSize(F);
911914

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

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

943+
#ifndef NDEBUG
944+
const uint64_t FinalOffset = Asm.getFragmentOffset(F);
945+
const uint64_t FinalSize = Asm.computeFragmentSize(F);
946+
assert(OrigOffset + OrigSize == FinalOffset + FinalSize &&
947+
"can't move start of next fragment!");
948+
assert(FinalSize == RemainingSize && "inconsistent size computation?");
949+
#endif
950+
939951
// If we're looking at a boundary align, make sure we don't try to pad
940952
// its target instructions for some following directive. Doing so would
941953
// break the alignment of the current boundary align.
@@ -949,7 +961,11 @@ bool X86AsmBackend::finishLayout(const MCAssembler &Asm) const {
949961
}
950962
}
951963

952-
return true;
964+
// The layout is done. Mark every fragment as valid.
965+
for (MCSection &Section : Asm) {
966+
Asm.getFragmentOffset(*Section.curFragList()->Tail);
967+
Asm.computeFragmentSize(*Section.curFragList()->Tail);
968+
}
953969
}
954970

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

0 commit comments

Comments
 (0)