@@ -46,23 +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 Chunk = std::unique_ptr<char []>(new char [Size]);
60
+ auto *F = reinterpret_cast <MCFragment *>(Chunk.get ());
61
+ FragStorage.push_back (std::move (Chunk));
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 = 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 = 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 ();
106
+ }
107
+
108
+ 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 ();
58
114
}
59
115
60
116
void MCObjectStreamer::appendContents (size_t Num, char Elt) {
61
- CurFrag->appendContents (Num, Elt);
117
+ ensureHeadroom (Num);
118
+ MutableArrayRef<char > Data (getCurFragEnd (), Num);
119
+ llvm::fill (Data, Elt);
120
+ CurFrag->FixedSize += Num;
121
+ FragSpace -= Num;
62
122
}
63
123
64
124
void MCObjectStreamer::addFixup (const MCExpr *Value, MCFixupKind Kind) {
65
- CurFrag->addFixup (MCFixup::create (CurFrag-> getFixedSize (), Value, Kind));
125
+ CurFrag->addFixup (MCFixup::create (getCurFragSize (), Value, Kind));
66
126
}
67
127
68
128
// As a compile-time optimization, avoid allocating and evaluating an MCExpr
@@ -111,6 +171,8 @@ void MCObjectStreamer::reset() {
111
171
}
112
172
EmitEHFrame = true ;
113
173
EmitDebugFrame = false ;
174
+ FragStorage.clear ();
175
+ FragSpace = 0 ;
114
176
MCStreamer::reset ();
115
177
}
116
178
@@ -139,7 +201,6 @@ void MCObjectStreamer::emitCFISections(bool EH, bool Debug, bool SFrame) {
139
201
void MCObjectStreamer::emitValueImpl (const MCExpr *Value, unsigned Size,
140
202
SMLoc Loc) {
141
203
MCStreamer::emitValueImpl (Value, Size, Loc);
142
- MCFragment *DF = getCurrentFragment ();
143
204
144
205
MCDwarfLineEntry::make (this , getCurrentSectionOnly ());
145
206
@@ -154,9 +215,9 @@ void MCObjectStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
154
215
emitIntValue (AbsValue, Size);
155
216
return ;
156
217
}
157
- DF-> addFixup ( MCFixup::create (DF-> getContents (). size (), Value,
158
- MCFixup::getDataKindForSize (Size) ));
159
- DF-> appendContents (Size, 0 );
218
+ ensureHeadroom (Size);
219
+ addFixup (Value, MCFixup::getDataKindForSize (Size));
220
+ appendContents (Size, 0 );
160
221
}
161
222
162
223
MCSymbol *MCObjectStreamer::emitCFILabel () {
@@ -190,7 +251,7 @@ void MCObjectStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
190
251
// section.
191
252
MCFragment *F = CurFrag;
192
253
Symbol->setFragment (F);
193
- Symbol->setOffset (F->getContents (). size ());
254
+ Symbol->setOffset (F->getFixedSize ());
194
255
195
256
emitPendingAssignments (Symbol);
196
257
}
@@ -256,20 +317,38 @@ void MCObjectStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
256
317
F0 = CurFrag;
257
318
}
258
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 = 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
+
259
335
auto &Subsections = Section->Subsections ;
260
336
size_t I = 0 , E = Subsections.size ();
261
337
while (I != E && Subsections[I].first < Subsection)
262
338
++I;
263
339
// If the subsection number is not in the sorted Subsections list, create a
264
340
// new fragment list.
265
341
if (I == E || Subsections[I].first != Subsection) {
266
- auto *F = getContext ().allocFragment <MCFragment>();
267
- F->setParent (Section);
268
342
Subsections.insert (Subsections.begin () + I,
269
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);
270
351
}
271
- Section->CurFragList = &Subsections[I].second ;
272
- CurFrag = Section->CurFragList ->Tail ;
273
352
274
353
// Define the section symbol at subsection 0's initial fragment if required.
275
354
if (!NewSec)
@@ -340,31 +419,29 @@ void MCObjectStreamer::emitInstToData(const MCInst &Inst,
340
419
MCFragment *F = getCurrentFragment ();
341
420
342
421
// Append the instruction to the data fragment.
343
- size_t CodeOffset = F->getContents ().size ();
422
+ size_t CodeOffset = getCurFragSize ();
423
+ SmallString<16 > Content;
344
424
SmallVector<MCFixup, 1 > Fixups;
345
- getAssembler ().getEmitter ().encodeInstruction (
346
- Inst, F->getContentsForAppending (), Fixups, STI);
347
- F->doneAppending ();
425
+ getAssembler ().getEmitter ().encodeInstruction (Inst, Content, Fixups, STI);
426
+ appendContents (Content);
348
427
F->setHasInstructions (STI);
349
428
350
429
if (Fixups.empty ())
351
430
return ;
352
431
bool MarkedLinkerRelaxable = false ;
353
432
for (auto &Fixup : Fixups) {
354
433
Fixup.setOffset (Fixup.getOffset () + CodeOffset);
355
- if (!Fixup.isLinkerRelaxable () || MarkedLinkerRelaxable )
434
+ if (!Fixup.isLinkerRelaxable ())
356
435
continue ;
357
- MarkedLinkerRelaxable = true ;
358
- // Set the fragment's order within the subsection for use by
359
- // MCAssembler::relaxAlign.
360
- auto *Sec = F->getParent ();
361
- if (!Sec->isLinkerRelaxable ())
362
- Sec->setLinkerRelaxable ();
436
+ F->setLinkerRelaxable ();
363
437
// Do not add data after a linker-relaxable instruction. The difference
364
438
// between a new label and a label at or before the linker-relaxable
365
439
// instruction cannot be resolved at assemble-time.
366
- F->setLinkerRelaxable ();
367
- newFragment ();
440
+ if (!MarkedLinkerRelaxable) {
441
+ MarkedLinkerRelaxable = true ;
442
+ getCurrentSectionOnly ()->setLinkerRelaxable ();
443
+ newFragment ();
444
+ }
368
445
}
369
446
F->appendFixups (Fixups);
370
447
}
@@ -538,8 +615,7 @@ void MCObjectStreamer::emitCVFileChecksumOffsetDirective(unsigned FileNo) {
538
615
539
616
void MCObjectStreamer::emitBytes (StringRef Data) {
540
617
MCDwarfLineEntry::make (this , getCurrentSectionOnly ());
541
- MCFragment *DF = getCurrentFragment ();
542
- DF->appendContents (ArrayRef (Data.data (), Data.size ()));
618
+ appendContents (ArrayRef (Data.data (), Data.size ()));
543
619
}
544
620
545
621
void MCObjectStreamer::emitValueToAlignment (Align Alignment, int64_t Fill,
0 commit comments