@@ -46,27 +46,83 @@ 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 (getContext ().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
- void MCObjectStreamer::insert (MCFragment *F ) {
54
- assert (F ->getKind () != MCFragment::FT_Data &&
87
+ void MCObjectStreamer::insert (MCFragment *Frag ) {
88
+ assert (Frag ->getKind () != MCFragment::FT_Data &&
55
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
+
104
+ addFragment (Frag);
56
105
addFragment (F);
57
- newFragment ();
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) {
69
- CurFrag->addFixup (MCFixup::create (CurFrag-> getFixedSize (), Value, Kind));
125
+ CurFrag->addFixup (MCFixup::create (getCurFragSize (), Value, Kind));
70
126
}
71
127
72
128
// As a compile-time optimization, avoid allocating and evaluating an MCExpr
@@ -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
MCStreamer::reset ();
119
177
}
120
178
@@ -143,7 +201,6 @@ void MCObjectStreamer::emitCFISections(bool EH, bool Debug, bool SFrame) {
143
201
void MCObjectStreamer::emitValueImpl (const MCExpr *Value, unsigned Size,
144
202
SMLoc Loc) {
145
203
MCStreamer::emitValueImpl (Value, Size, Loc);
146
- MCFragment *DF = getCurrentFragment ();
147
204
148
205
MCDwarfLineEntry::make (this , getCurrentSectionOnly ());
149
206
@@ -158,9 +215,9 @@ void MCObjectStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
158
215
emitIntValue (AbsValue, Size);
159
216
return ;
160
217
}
161
- DF-> addFixup ( MCFixup::create (DF-> getContents (). size (), Value,
162
- MCFixup::getDataKindForSize (Size) ));
163
- DF-> appendContents (Size, 0 );
218
+ ensureHeadroom (Size);
219
+ addFixup (Value, MCFixup::getDataKindForSize (Size));
220
+ appendContents (Size, 0 );
164
221
}
165
222
166
223
MCSymbol *MCObjectStreamer::emitCFILabel () {
@@ -194,7 +251,7 @@ void MCObjectStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
194
251
// section.
195
252
MCFragment *F = CurFrag;
196
253
Symbol->setFragment (F);
197
- Symbol->setOffset (F->getContents (). size ());
254
+ Symbol->setOffset (F->getFixedSize ());
198
255
199
256
emitPendingAssignments (Symbol);
200
257
}
@@ -260,20 +317,38 @@ void MCObjectStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
260
317
F0 = CurFrag;
261
318
}
262
319
320
+ // To maintain connectivity between CurFrag and FragSpace when CurFrag is
321
+ // modified, allocate an empty fragment and append it to the fragment list.
322
+ // (Subsections[I].second.Tail is not connected to FragSpace.)
323
+ MCFragment *F;
324
+ if (LLVM_LIKELY (sizeof (MCFragment) + NewFragHeadroom <= FragSpace)) {
325
+ auto End = reinterpret_cast <size_t >(getCurFragEnd ());
326
+ F = reinterpret_cast <MCFragment *>(
327
+ alignToPowerOf2 (End, alignof (MCFragment)));
328
+ FragSpace -= size_t (F) - End + sizeof (MCFragment);
329
+ } else {
330
+ F = allocFragSpace (0 );
331
+ }
332
+ new (F) MCFragment ();
333
+ F->setParent (Section);
334
+
263
335
auto &Subsections = Section->Subsections ;
264
336
size_t I = 0 , E = Subsections.size ();
265
337
while (I != E && Subsections[I].first < Subsection)
266
338
++I;
267
339
// If the subsection number is not in the sorted Subsections list, create a
268
340
// new fragment list.
269
341
if (I == E || Subsections[I].first != Subsection) {
270
- auto *F = getContext ().allocFragment <MCFragment>();
271
- F->setParent (Section);
272
342
Subsections.insert (Subsections.begin () + I,
273
343
{Subsection, MCSection::FragList{F, F}});
344
+ Section->CurFragList = &Subsections[I].second ;
345
+ CurFrag = F;
346
+ } else {
347
+ Section->CurFragList = &Subsections[I].second ;
348
+ CurFrag = Subsections[I].second .Tail ;
349
+ // Ensure CurFrag is associated with FragSpace.
350
+ addFragment (F);
274
351
}
275
- Section->CurFragList = &Subsections[I].second ;
276
- CurFrag = Section->CurFragList ->Tail ;
277
352
278
353
// Define the section symbol at subsection 0's initial fragment if required.
279
354
if (!NewSec)
@@ -344,11 +419,15 @@ void MCObjectStreamer::emitInstToData(const MCInst &Inst,
344
419
MCFragment *F = getCurrentFragment ();
345
420
346
421
// Append the instruction to the data fragment.
347
- size_t CodeOffset = F->getContents ().size ();
422
+ size_t CodeOffset = getCurFragSize ();
423
+ SmallString<16 > Content;
348
424
SmallVector<MCFixup, 1 > Fixups;
349
- getAssembler ().getEmitter ().encodeInstruction (
350
- Inst, F->getContentsForAppending (), Fixups, STI);
351
- F->doneAppending ();
425
+ getAssembler ().getEmitter ().encodeInstruction (Inst, Content, Fixups, STI);
426
+ appendContents (Content);
427
+ if (CurFrag != F) {
428
+ F = CurFrag;
429
+ CodeOffset = 0 ;
430
+ }
352
431
F->setHasInstructions (STI);
353
432
354
433
if (Fixups.empty ())
0 commit comments