@@ -46,23 +46,84 @@ MCAssembler *MCObjectStreamer::getAssemblerPtr() {
46
46
return nullptr ;
47
47
}
48
48
49
+ constexpr size_t FragChunkSize = 16384 ;
50
+ // Ensure the new fragment can at least at least a few bytes.
51
+ constexpr size_t NewFragHeadroom = 8 ;
52
+
53
+ static_assert (NewFragHeadroom >= alignof (MCFragment));
54
+ static_assert (FragChunkSize >= sizeof (MCFragment) + NewFragHeadroom);
55
+
56
+ MCFragment *MCObjectStreamer::allocFragSpace (size_t Headroom) {
57
+ auto Size = std::max (FragChunkSize, 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
+ // Allocate an empty fragment, potentially reusing the space associated with
91
+ // CurFrag.
92
+ MCFragment *F;
93
+ if (LLVM_LIKELY (sizeof (MCFragment) + NewFragHeadroom <= FragSpace)) {
94
+ auto End = size_t (getCurFragEnd ());
95
+ F = reinterpret_cast <MCFragment *>(
96
+ alignToPowerOf2 (End, alignof (MCFragment)));
97
+ FragSpace -= size_t (F) - End + sizeof (MCFragment);
98
+ } else {
99
+ F = allocFragSpace (0 );
100
+ }
101
+
102
+ // Add Frag, which destroys CurFrag and the associated space.
103
+ addFragment (Frag);
104
+ new (F) MCFragment ();
105
+ // Add the empty fragment, which restores CurFrag and the associated space.
56
106
addFragment (F);
57
- newFragment ();
107
+ }
108
+
109
+ void MCObjectStreamer::appendContents (ArrayRef<char > Contents) {
110
+ ensureHeadroom (Contents.size ());
111
+ assert (FragSpace >= Contents.size ());
112
+ llvm::copy (Contents, getCurFragEnd ());
113
+ CurFrag->FixedSize += Contents.size ();
114
+ FragSpace -= Contents.size ();
58
115
}
59
116
60
117
void MCObjectStreamer::appendContents (size_t Num, char Elt) {
61
- CurFrag->appendContents (Num, Elt);
118
+ ensureHeadroom (Num);
119
+ MutableArrayRef<char > Data (getCurFragEnd (), Num);
120
+ llvm::fill (Data, Elt);
121
+ CurFrag->FixedSize += Num;
122
+ FragSpace -= Num;
62
123
}
63
124
64
125
void MCObjectStreamer::addFixup (const MCExpr *Value, MCFixupKind Kind) {
65
- CurFrag->addFixup (MCFixup::create (CurFrag-> getFixedSize (), Value, Kind));
126
+ CurFrag->addFixup (MCFixup::create (getCurFragSize (), Value, Kind));
66
127
}
67
128
68
129
// As a compile-time optimization, avoid allocating and evaluating an MCExpr
@@ -111,6 +172,8 @@ void MCObjectStreamer::reset() {
111
172
}
112
173
EmitEHFrame = true ;
113
174
EmitDebugFrame = false ;
175
+ FragStorage.clear ();
176
+ FragSpace = 0 ;
114
177
MCStreamer::reset ();
115
178
}
116
179
@@ -139,7 +202,6 @@ void MCObjectStreamer::emitCFISections(bool EH, bool Debug, bool SFrame) {
139
202
void MCObjectStreamer::emitValueImpl (const MCExpr *Value, unsigned Size,
140
203
SMLoc Loc) {
141
204
MCStreamer::emitValueImpl (Value, Size, Loc);
142
- MCFragment *DF = getCurrentFragment ();
143
205
144
206
MCDwarfLineEntry::make (this , getCurrentSectionOnly ());
145
207
@@ -154,9 +216,9 @@ void MCObjectStreamer::emitValueImpl(const MCExpr *Value, unsigned Size,
154
216
emitIntValue (AbsValue, Size);
155
217
return ;
156
218
}
157
- DF-> addFixup ( MCFixup::create (DF-> getContents (). size (), Value,
158
- MCFixup::getDataKindForSize (Size) ));
159
- DF-> appendContents (Size, 0 );
219
+ ensureHeadroom (Size);
220
+ addFixup (Value, MCFixup::getDataKindForSize (Size));
221
+ appendContents (Size, 0 );
160
222
}
161
223
162
224
MCSymbol *MCObjectStreamer::emitCFILabel () {
@@ -190,7 +252,7 @@ void MCObjectStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
190
252
// section.
191
253
MCFragment *F = CurFrag;
192
254
Symbol->setFragment (F);
193
- Symbol->setOffset (F->getContents (). size ());
255
+ Symbol->setOffset (F->getFixedSize ());
194
256
195
257
emitPendingAssignments (Symbol);
196
258
}
@@ -256,20 +318,38 @@ void MCObjectStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
256
318
F0 = CurFrag;
257
319
}
258
320
321
+ // CurFrag will be changed. To ensure that FragSpace remains connected with
322
+ // CurFrag, allocate an empty fragment and add it to the fragment list.
323
+ // (Subsections[I].second.Tail is disconnected with FragSpace.)
324
+ MCFragment *F;
325
+ if (LLVM_LIKELY (sizeof (MCFragment) + NewFragHeadroom <= FragSpace)) {
326
+ auto End = 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
+
259
336
auto &Subsections = Section->Subsections ;
260
337
size_t I = 0 , E = Subsections.size ();
261
338
while (I != E && Subsections[I].first < Subsection)
262
339
++I;
263
340
// If the subsection number is not in the sorted Subsections list, create a
264
341
// new fragment list.
265
342
if (I == E || Subsections[I].first != Subsection) {
266
- auto *F = getContext ().allocFragment <MCFragment>();
267
- F->setParent (Section);
268
343
Subsections.insert (Subsections.begin () + I,
269
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);
270
352
}
271
- Section->CurFragList = &Subsections[I].second ;
272
- CurFrag = Section->CurFragList ->Tail ;
273
353
274
354
// Define the section symbol at subsection 0's initial fragment if required.
275
355
if (!NewSec)
@@ -340,31 +420,29 @@ void MCObjectStreamer::emitInstToData(const MCInst &Inst,
340
420
MCFragment *F = getCurrentFragment ();
341
421
342
422
// Append the instruction to the data fragment.
343
- size_t CodeOffset = F->getContents ().size ();
423
+ size_t CodeOffset = getCurFragSize ();
424
+ SmallString<16 > Content;
344
425
SmallVector<MCFixup, 1 > Fixups;
345
- getAssembler ().getEmitter ().encodeInstruction (
346
- Inst, F->getContentsForAppending (), Fixups, STI);
347
- F->doneAppending ();
426
+ getAssembler ().getEmitter ().encodeInstruction (Inst, Content, Fixups, STI);
427
+ appendContents (Content);
348
428
F->setHasInstructions (STI);
349
429
350
430
if (Fixups.empty ())
351
431
return ;
352
432
bool MarkedLinkerRelaxable = false ;
353
433
for (auto &Fixup : Fixups) {
354
434
Fixup.setOffset (Fixup.getOffset () + CodeOffset);
355
- if (!Fixup.isLinkerRelaxable () || MarkedLinkerRelaxable )
435
+ if (!Fixup.isLinkerRelaxable ())
356
436
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 ();
437
+ F->setLinkerRelaxable ();
363
438
// Do not add data after a linker-relaxable instruction. The difference
364
439
// between a new label and a label at or before the linker-relaxable
365
440
// instruction cannot be resolved at assemble-time.
366
- F->setLinkerRelaxable ();
367
- newFragment ();
441
+ if (!MarkedLinkerRelaxable) {
442
+ MarkedLinkerRelaxable = true ;
443
+ getCurrentSectionOnly ()->setLinkerRelaxable ();
444
+ newFragment ();
445
+ }
368
446
}
369
447
F->appendFixups (Fixups);
370
448
}
@@ -538,8 +616,7 @@ void MCObjectStreamer::emitCVFileChecksumOffsetDirective(unsigned FileNo) {
538
616
539
617
void MCObjectStreamer::emitBytes (StringRef Data) {
540
618
MCDwarfLineEntry::make (this , getCurrentSectionOnly ());
541
- MCFragment *DF = getCurrentFragment ();
542
- DF->appendContents (ArrayRef (Data.data (), Data.size ()));
619
+ appendContents (ArrayRef (Data.data (), Data.size ()));
543
620
}
544
621
545
622
void MCObjectStreamer::emitValueToAlignment (Align Alignment, int64_t Fill,
0 commit comments