Skip to content

Commit a2fef66

Browse files
committed
Revert "MCFragment: Use trailing data for fixed-size part"
This reverts commit f1aa605 (reland of #150846), fixing conflicts. It caused ClangBuiltLinux/linux#2116 , which surfaced after a subsequent commit faa931b decreased sizeof(MCFragment). ``` % /tmp/Debug/bin/clang "-cc1as" "-triple" "aarch64" "-filetype" "obj" "-main-file-name" "a.s" "-o" "a.o" "a.s" clang: /home/ray/llvm/llvm/lib/MC/MCAssembler.cpp:615: void llvm::MCAssembler::writeSectionData(raw_ostream &, const MCSection *) const: Assertion `getContext().hadError() || OS.tell() - Start == getSectionAddressSize(*Sec)' failed. PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace, preprocessed source, and associated run script. Stack dump: 0. Program arguments: /tmp/Debug/bin/clang -cc1as -triple aarch64 -filetype obj -main-file-name a.s -o a.o a.s Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it): 0 libLLVMSupport.so.22.0git 0x00007cf91eb753cd llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 61 fish: Job 1, '/tmp/Debug/bin/clang "-cc1as" "…' terminated by signal SIGABRT (Abort) ``` The test is sensitive to precise fragment offsets. Using llvm-mc -filetype=obj -triple=aarch64 a.s does not replicate the issue. However, clang -cc1as includes an unnecessary `initSection` (adding an extra FT_Align), which causes the problem.
1 parent 144cd87 commit a2fef66

File tree

7 files changed

+63
-143
lines changed

7 files changed

+63
-143
lines changed

llvm/include/llvm/MC/MCObjectStreamer.h

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,6 @@ class MCObjectStreamer : public MCStreamer {
5252
DenseMap<const MCSymbol *, SmallVector<PendingAssignment, 1>>
5353
pendingAssignments;
5454

55-
SmallVector<std::unique_ptr<uint8_t[]>, 0> FragStorage;
56-
// Available bytes in the current block for trailing data or new fragments.
57-
size_t FragSpace = 0;
5855
// Used to allocate special fragments that do not use MCFragment's fixed-size
5956
// part.
6057
BumpPtrAllocator SpecialFragAllocator;
@@ -89,28 +86,25 @@ class MCObjectStreamer : public MCStreamer {
8986
/// \name MCStreamer Interface
9087
/// @{
9188

92-
uint8_t *getCurFragEnd() const {
93-
return reinterpret_cast<uint8_t *>(CurFrag + 1) + CurFrag->getFixedSize();
94-
}
95-
MCFragment *allocFragSpace(size_t Headroom);
9689
// Add a new fragment to the current section without a variable-size tail.
9790
void newFragment();
9891

92+
template <typename FT, typename... Args> FT *allocFragment(Args &&...args) {
93+
auto *F = new (SpecialFragAllocator.Allocate(sizeof(FT), alignof(FT)))
94+
FT(std::forward<Args>(args)...);
95+
return F;
96+
}
9997
// Add a new special fragment to the current section and start a new empty
10098
// fragment.
10199
template <typename FT, typename... Args>
102100
FT *newSpecialFragment(Args &&...args) {
103-
auto *F = new (SpecialFragAllocator.Allocate(sizeof(FT), alignof(FT)))
104-
FT(std::forward<Args>(args)...);
101+
auto *F = allocFragment<FT, Args...>(std::forward<Args>(args)...);
105102
addSpecialFragment(F);
106103
return F;
107104
}
108105

109-
void ensureHeadroom(size_t Headroom);
110106
void appendContents(ArrayRef<char> Contents);
111-
void appendContents(size_t Num, uint8_t Elt);
112-
// Add a fixup to the current fragment. Call ensureHeadroom beforehand to
113-
// ensure the fixup and appended content apply to the same fragment.
107+
void appendContents(size_t Num, char Elt);
114108
void addFixup(const MCExpr *Value, MCFixupKind Kind);
115109

116110
void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;

llvm/include/llvm/MC/MCSection.h

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,10 @@ class MCFragment {
9393
bool AllowAutoPadding : 1;
9494

9595
// Track content and fixups for the fixed-size part as fragments are
96-
// appended to the section. The content is stored as trailing data of the
97-
// MCFragment. The content remains immutable, except when modified by
98-
// applyFixup.
99-
uint32_t FixedSize = 0;
96+
// appended to the section. The content remains immutable, except when
97+
// modified by applyFixup.
98+
uint32_t ContentStart = 0;
99+
uint32_t ContentEnd = 0;
100100
uint32_t FixupStart = 0;
101101
uint32_t FixupEnd = 0;
102102

@@ -189,6 +189,18 @@ class MCFragment {
189189
//== Content-related functions manage parent's storage using ContentStart and
190190
// ContentSize.
191191

192+
// Get a SmallVector reference. The caller should call doneAppending to update
193+
// `ContentEnd`.
194+
SmallVectorImpl<char> &getContentsForAppending();
195+
void doneAppending();
196+
void appendContents(ArrayRef<char> Contents) {
197+
getContentsForAppending().append(Contents.begin(), Contents.end());
198+
doneAppending();
199+
}
200+
void appendContents(size_t Num, char Elt) {
201+
getContentsForAppending().append(Num, Elt);
202+
doneAppending();
203+
}
192204
MutableArrayRef<char> getContents();
193205
ArrayRef<char> getContents() const;
194206

@@ -197,10 +209,10 @@ class MCFragment {
197209
MutableArrayRef<char> getVarContents();
198210
ArrayRef<char> getVarContents() const;
199211

200-
size_t getFixedSize() const { return FixedSize; }
212+
size_t getFixedSize() const { return ContentEnd - ContentStart; }
201213
size_t getVarSize() const { return VarContentEnd - VarContentStart; }
202214
size_t getSize() const {
203-
return FixedSize + (VarContentEnd - VarContentStart);
215+
return ContentEnd - ContentStart + (VarContentEnd - VarContentStart);
204216
}
205217

206218
//== Fixup-related functions manage parent's storage using FixupStart and
@@ -615,11 +627,28 @@ class LLVM_ABI MCSection {
615627
bool isBssSection() const { return IsBss; }
616628
};
617629

630+
inline SmallVectorImpl<char> &MCFragment::getContentsForAppending() {
631+
SmallVectorImpl<char> &S = getParent()->ContentStorage;
632+
if (LLVM_UNLIKELY(ContentEnd != S.size())) {
633+
// Move the elements to the end. Reserve space to avoid invalidating
634+
// S.begin()+I for `append`.
635+
auto Size = ContentEnd - ContentStart;
636+
auto I = std::exchange(ContentStart, S.size());
637+
S.reserve(S.size() + Size);
638+
S.append(S.begin() + I, S.begin() + I + Size);
639+
}
640+
return S;
641+
}
642+
inline void MCFragment::doneAppending() {
643+
ContentEnd = getParent()->ContentStorage.size();
644+
}
618645
inline MutableArrayRef<char> MCFragment::getContents() {
619-
return {reinterpret_cast<char *>(this + 1), FixedSize};
646+
return MutableArrayRef(getParent()->ContentStorage)
647+
.slice(ContentStart, ContentEnd - ContentStart);
620648
}
621649
inline ArrayRef<char> MCFragment::getContents() const {
622-
return {reinterpret_cast<const char *>(this + 1), FixedSize};
650+
return ArrayRef(getParent()->ContentStorage)
651+
.slice(ContentStart, ContentEnd - ContentStart);
623652
}
624653

625654
inline MutableArrayRef<char> MCFragment::getVarContents() {

llvm/lib/MC/MCObjectStreamer.cpp

Lines changed: 19 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -46,79 +46,23 @@ MCAssembler *MCObjectStreamer::getAssemblerPtr() {
4646
return nullptr;
4747
}
4848

49-
constexpr size_t FragBlockSize = 16384;
50-
// Ensure the new fragment can at least store a few bytes.
51-
constexpr size_t NewFragHeadroom = 8;
52-
53-
static_assert(NewFragHeadroom >= alignof(MCFragment));
54-
static_assert(FragBlockSize >= sizeof(MCFragment) + NewFragHeadroom);
55-
56-
MCFragment *MCObjectStreamer::allocFragSpace(size_t Headroom) {
57-
auto Size = std::max(FragBlockSize, sizeof(MCFragment) + Headroom);
58-
FragSpace = Size - sizeof(MCFragment);
59-
auto Block = std::unique_ptr<uint8_t[]>(new uint8_t[Size]);
60-
auto *F = reinterpret_cast<MCFragment *>(Block.get());
61-
FragStorage.push_back(std::move(Block));
62-
return F;
63-
}
64-
6549
void MCObjectStreamer::newFragment() {
66-
MCFragment *F;
67-
if (LLVM_LIKELY(sizeof(MCFragment) + NewFragHeadroom <= FragSpace)) {
68-
auto End = reinterpret_cast<size_t>(getCurFragEnd());
69-
F = reinterpret_cast<MCFragment *>(
70-
alignToPowerOf2(End, alignof(MCFragment)));
71-
FragSpace -= size_t(F) - End + sizeof(MCFragment);
72-
} else {
73-
F = allocFragSpace(0);
74-
}
75-
new (F) MCFragment();
76-
addFragment(F);
77-
}
78-
79-
void MCObjectStreamer::ensureHeadroom(size_t Headroom) {
80-
if (Headroom <= FragSpace)
81-
return;
82-
auto *F = allocFragSpace(Headroom);
83-
new (F) MCFragment();
84-
addFragment(F);
50+
addFragment(allocFragment<MCFragment>());
8551
}
8652

8753
void MCObjectStreamer::addSpecialFragment(MCFragment *Frag) {
8854
assert(Frag->getKind() != MCFragment::FT_Data &&
89-
"F should have a variable-size tail");
90-
// Frag is not connected to FragSpace. Before modifying CurFrag with
91-
// addFragment(Frag), allocate an empty fragment to maintain FragSpace
92-
// connectivity, potentially reusing CurFrag's associated space.
93-
MCFragment *F;
94-
if (LLVM_LIKELY(sizeof(MCFragment) + NewFragHeadroom <= FragSpace)) {
95-
auto End = reinterpret_cast<size_t>(getCurFragEnd());
96-
F = reinterpret_cast<MCFragment *>(
97-
alignToPowerOf2(End, alignof(MCFragment)));
98-
FragSpace -= size_t(F) - End + sizeof(MCFragment);
99-
} else {
100-
F = allocFragSpace(0);
101-
}
102-
new (F) MCFragment();
103-
55+
"Frag should have a variable-size tail");
10456
addFragment(Frag);
105-
addFragment(F);
57+
newFragment();
10658
}
10759

10860
void MCObjectStreamer::appendContents(ArrayRef<char> Contents) {
109-
ensureHeadroom(Contents.size());
110-
assert(FragSpace >= Contents.size());
111-
llvm::copy(Contents, getCurFragEnd());
112-
CurFrag->FixedSize += Contents.size();
113-
FragSpace -= Contents.size();
61+
CurFrag->appendContents(Contents);
11462
}
11563

116-
void MCObjectStreamer::appendContents(size_t Num, uint8_t Elt) {
117-
ensureHeadroom(Num);
118-
MutableArrayRef<uint8_t> Data(getCurFragEnd(), Num);
119-
llvm::fill(Data, Elt);
120-
CurFrag->FixedSize += Num;
121-
FragSpace -= Num;
64+
void MCObjectStreamer::appendContents(size_t Num, char Elt) {
65+
CurFrag->appendContents(Num, Elt);
12266
}
12367

12468
void MCObjectStreamer::addFixup(const MCExpr *Value, MCFixupKind Kind) {
@@ -171,8 +115,6 @@ void MCObjectStreamer::reset() {
171115
}
172116
EmitEHFrame = true;
173117
EmitDebugFrame = false;
174-
FragStorage.clear();
175-
FragSpace = 0;
176118
SpecialFragAllocator.Reset();
177119
MCStreamer::reset();
178120
}
@@ -202,6 +144,7 @@ void MCObjectStreamer::emitCFISections(bool EH, bool Debug, bool SFrame) {
202144
void MCObjectStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
203145
SMLoc Loc) {
204146
MCStreamer::emitValueImpl(Value, Size, Loc);
147+
MCFragment *DF = getCurrentFragment();
205148

206149
MCDwarfLineEntry::make(this, getCurrentSectionOnly());
207150

@@ -216,9 +159,9 @@ void MCObjectStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
216159
emitIntValue(AbsValue, Size);
217160
return;
218161
}
219-
ensureHeadroom(Size);
220-
addFixup(Value, MCFixup::getDataKindForSize(Size));
221-
appendContents(Size, 0);
162+
DF->addFixup(MCFixup::create(DF->getContents().size(), Value,
163+
MCFixup::getDataKindForSize(Size)));
164+
DF->appendContents(Size, 0);
222165
}
223166

224167
MCSymbol *MCObjectStreamer::emitCFILabel() {
@@ -252,7 +195,7 @@ void MCObjectStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
252195
// section.
253196
MCFragment *F = CurFrag;
254197
Symbol->setFragment(F);
255-
Symbol->setOffset(F->getFixedSize());
198+
Symbol->setOffset(F->getContents().size());
256199

257200
emitPendingAssignments(Symbol);
258201
}
@@ -318,38 +261,20 @@ void MCObjectStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
318261
F0 = CurFrag;
319262
}
320263

321-
// To maintain connectivity between CurFrag and FragSpace when CurFrag is
322-
// modified, allocate an empty fragment and append it to the fragment list.
323-
// (Subsections[I].second.Tail is not connected to FragSpace.)
324-
MCFragment *F;
325-
if (LLVM_LIKELY(sizeof(MCFragment) + NewFragHeadroom <= FragSpace)) {
326-
auto End = reinterpret_cast<size_t>(getCurFragEnd());
327-
F = reinterpret_cast<MCFragment *>(
328-
alignToPowerOf2(End, alignof(MCFragment)));
329-
FragSpace -= size_t(F) - End + sizeof(MCFragment);
330-
} else {
331-
F = allocFragSpace(0);
332-
}
333-
new (F) MCFragment();
334-
F->setParent(Section);
335-
336264
auto &Subsections = Section->Subsections;
337265
size_t I = 0, E = Subsections.size();
338266
while (I != E && Subsections[I].first < Subsection)
339267
++I;
340268
// If the subsection number is not in the sorted Subsections list, create a
341269
// new fragment list.
342270
if (I == E || Subsections[I].first != Subsection) {
271+
auto *F = allocFragment<MCFragment>();
272+
F->setParent(Section);
343273
Subsections.insert(Subsections.begin() + I,
344274
{Subsection, MCSection::FragList{F, F}});
345-
Section->CurFragList = &Subsections[I].second;
346-
CurFrag = F;
347-
} else {
348-
Section->CurFragList = &Subsections[I].second;
349-
CurFrag = Subsections[I].second.Tail;
350-
// Ensure CurFrag is associated with FragSpace.
351-
addFragment(F);
352275
}
276+
Section->CurFragList = &Subsections[I].second;
277+
CurFrag = Section->CurFragList->Tail;
353278

354279
// Define the section symbol at subsection 0's initial fragment if required.
355280
if (!NewSec)
@@ -420,15 +345,11 @@ void MCObjectStreamer::emitInstToData(const MCInst &Inst,
420345
MCFragment *F = getCurrentFragment();
421346

422347
// Append the instruction to the data fragment.
423-
size_t CodeOffset = getCurFragSize();
424-
SmallString<16> Content;
348+
size_t CodeOffset = F->getContents().size();
425349
SmallVector<MCFixup, 1> Fixups;
426-
getAssembler().getEmitter().encodeInstruction(Inst, Content, Fixups, STI);
427-
appendContents(Content);
428-
if (CurFrag != F) {
429-
F = CurFrag;
430-
CodeOffset = 0;
431-
}
350+
getAssembler().getEmitter().encodeInstruction(
351+
Inst, F->getContentsForAppending(), Fixups, STI);
352+
F->doneAppending();
432353
F->setHasInstructions(STI);
433354

434355
if (Fixups.empty())

llvm/lib/MC/MCWin64EH.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -318,9 +318,6 @@ static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
318318

319319
// Emit the epilog instructions.
320320
if (EnableUnwindV2) {
321-
// Ensure the fixups and appended content apply to the same fragment.
322-
OS->ensureHeadroom(info->EpilogMap.size() * 2);
323-
324321
bool IsLast = true;
325322
for (const auto &Epilog : llvm::reverse(info->EpilogMap)) {
326323
if (IsLast) {

llvm/lib/MC/MCWinCOFFStreamer.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,6 @@ void MCWinCOFFStreamer::emitCOFFSymbolIndex(MCSymbol const *Symbol) {
279279
void MCWinCOFFStreamer::emitCOFFSectionIndex(const MCSymbol *Symbol) {
280280
visitUsedSymbol(*Symbol);
281281
const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext());
282-
ensureHeadroom(2);
283282
addFixup(SRE, FK_SecRel_2);
284283
appendContents(2, 0);
285284
}
@@ -293,7 +292,6 @@ void MCWinCOFFStreamer::emitCOFFSecRel32(const MCSymbol *Symbol,
293292
if (Offset)
294293
MCE = MCBinaryExpr::createAdd(
295294
MCE, MCConstantExpr::create(Offset, getContext()), getContext());
296-
ensureHeadroom(4);
297295
addFixup(MCE, FK_SecRel_4);
298296
// Emit 4 bytes (zeros) to the object file.
299297
appendContents(4, 0);
@@ -309,7 +307,6 @@ void MCWinCOFFStreamer::emitCOFFImgRel32(const MCSymbol *Symbol,
309307
if (Offset)
310308
MCE = MCBinaryExpr::createAdd(
311309
MCE, MCConstantExpr::create(Offset, getContext()), getContext());
312-
ensureHeadroom(4);
313310
addFixup(MCE, FK_Data_4);
314311
// Emit 4 bytes (zeros) to the object file.
315312
appendContents(4, 0);
@@ -320,7 +317,6 @@ void MCWinCOFFStreamer::emitCOFFSecNumber(MCSymbol const *Symbol) {
320317
// Create Symbol for section number.
321318
const MCExpr *MCE = MCCOFFSectionNumberTargetExpr::create(
322319
*Symbol, this->getWriter(), getContext());
323-
ensureHeadroom(4);
324320
addFixup(MCE, FK_Data_4);
325321
// Emit 4 bytes (zeros) to the object file.
326322
appendContents(4, 0);
@@ -331,7 +327,6 @@ void MCWinCOFFStreamer::emitCOFFSecOffset(MCSymbol const *Symbol) {
331327
// Create Symbol for section offset.
332328
const MCExpr *MCE =
333329
MCCOFFSectionOffsetTargetExpr::create(*Symbol, getContext());
334-
ensureHeadroom(4);
335330
addFixup(MCE, FK_Data_4);
336331
// Emit 4 bytes (zeros) to the object file.
337332
appendContents(4, 0);

0 commit comments

Comments
 (0)