@@ -46,23 +46,79 @@ MCAssembler *MCObjectStreamer::getAssemblerPtr() {
46
46
return nullptr ;
47
47
}
48
48
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
+
49
65
void MCObjectStreamer::newFragment () {
50
- addFragment (allocFragment<MCFragment>());
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);
51
85
}
52
86
53
87
void MCObjectStreamer::addSpecialFragment (MCFragment *Frag) {
54
88
assert (Frag->getKind () != MCFragment::FT_Data &&
55
89
" Frag 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
+
56
104
addFragment (Frag);
57
- newFragment ( );
105
+ addFragment (F );
58
106
}
59
107
60
108
void MCObjectStreamer::appendContents (ArrayRef<char > Contents) {
61
- CurFrag->appendContents (Contents);
109
+ ensureHeadroom (Contents.size ());
110
+ assert (FragSpace >= Contents.size ());
111
+ llvm::copy (Contents, getCurFragEnd ());
112
+ CurFrag->FixedSize += Contents.size ();
113
+ FragSpace -= Contents.size ();
62
114
}
63
115
64
- void MCObjectStreamer::appendContents (size_t Num, char Elt) {
65
- CurFrag->appendContents (Num, Elt);
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;
66
122
}
67
123
68
124
void MCObjectStreamer::addFixup (const MCExpr *Value, MCFixupKind Kind) {
@@ -115,6 +171,8 @@ void MCObjectStreamer::reset() {
115
171
}
116
172
EmitEHFrame = true ;
117
173
EmitDebugFrame = false ;
174
+ FragStorage.clear ();
175
+ FragSpace = 0 ;
118
176
SpecialFragAllocator.Reset ();
119
177
MCStreamer::reset ();
120
178
}
@@ -144,7 +202,6 @@ void MCObjectStreamer::emitCFISections(bool EH, bool Debug, bool SFrame) {
144
202
void MCObjectStreamer::emitValueImpl (const MCExpr *Value, unsigned Size,
145
203
SMLoc Loc) {
146
204
MCStreamer::emitValueImpl (Value, Size, Loc);
147
- MCFragment *DF = getCurrentFragment ();
148
205
149
206
MCDwarfLineEntry::make (this , getCurrentSectionOnly ());
150
207
@@ -159,9 +216,9 @@ void MCObjectStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
159
216
emitIntValue (AbsValue, Size);
160
217
return ;
161
218
}
162
- DF-> addFixup ( MCFixup::create (DF-> getContents (). size (), Value,
163
- MCFixup::getDataKindForSize (Size) ));
164
- DF-> appendContents (Size, 0 );
219
+ ensureHeadroom (Size);
220
+ addFixup (Value, MCFixup::getDataKindForSize (Size));
221
+ appendContents (Size, 0 );
165
222
}
166
223
167
224
MCSymbol *MCObjectStreamer::emitCFILabel () {
@@ -195,7 +252,7 @@ void MCObjectStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
195
252
// section.
196
253
MCFragment *F = CurFrag;
197
254
Symbol->setFragment (F);
198
- Symbol->setOffset (F->getContents (). size ());
255
+ Symbol->setOffset (F->getFixedSize ());
199
256
200
257
emitPendingAssignments (Symbol);
201
258
}
@@ -261,20 +318,38 @@ void MCObjectStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
261
318
F0 = CurFrag;
262
319
}
263
320
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
+
264
336
auto &Subsections = Section->Subsections ;
265
337
size_t I = 0 , E = Subsections.size ();
266
338
while (I != E && Subsections[I].first < Subsection)
267
339
++I;
268
340
// If the subsection number is not in the sorted Subsections list, create a
269
341
// new fragment list.
270
342
if (I == E || Subsections[I].first != Subsection) {
271
- auto *F = allocFragment<MCFragment>();
272
- F->setParent (Section);
273
343
Subsections.insert (Subsections.begin () + I,
274
344
{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);
275
352
}
276
- Section->CurFragList = &Subsections[I].second ;
277
- CurFrag = Section->CurFragList ->Tail ;
278
353
279
354
// Define the section symbol at subsection 0's initial fragment if required.
280
355
if (!NewSec)
@@ -345,11 +420,15 @@ void MCObjectStreamer::emitInstToData(const MCInst &Inst,
345
420
MCFragment *F = getCurrentFragment ();
346
421
347
422
// Append the instruction to the data fragment.
348
- size_t CodeOffset = F->getContents ().size ();
423
+ size_t CodeOffset = getCurFragSize ();
424
+ SmallString<16 > Content;
349
425
SmallVector<MCFixup, 1 > Fixups;
350
- getAssembler ().getEmitter ().encodeInstruction (
351
- Inst, F->getContentsForAppending (), Fixups, STI);
352
- F->doneAppending ();
426
+ getAssembler ().getEmitter ().encodeInstruction (Inst, Content, Fixups, STI);
427
+ appendContents (Content);
428
+ if (CurFrag != F) {
429
+ F = CurFrag;
430
+ CodeOffset = 0 ;
431
+ }
353
432
F->setHasInstructions (STI);
354
433
355
434
if (Fixups.empty ())
0 commit comments