LLVM: lib/Support/RewriteRope.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
15#include
16#include
17#include
18
19using namespace llvm;
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64namespace {
65
66
67
68
69
70
71
72
73
74
75
76class RopePieceBTreeNode {
77protected:
78
79
80
81
82
83 enum { WidthFactor = 8 };
84
85
86
87 unsigned Size = 0;
88
89
90
91 bool IsLeaf;
92
93 RopePieceBTreeNode(bool isLeaf) : IsLeaf(isLeaf) {}
94 ~RopePieceBTreeNode() = default;
95
96public:
97 bool isLeaf() const { return IsLeaf; }
98 unsigned size() const { return Size; }
99
100 void Destroy();
101
102
103
104
105
106
107
108 RopePieceBTreeNode *split(unsigned Offset);
109
110
111
112
113
114
115
116 RopePieceBTreeNode *insert(unsigned Offset, const RopePiece &R);
117
118
119
120 void erase(unsigned Offset, unsigned NumBytes);
121};
122
123
124
125
126
127
128
129
130
131
132
133
134class RopePieceBTreeLeaf : public RopePieceBTreeNode {
135
136
137 unsigned char NumPieces = 0;
138
139
140 RopePiece Pieces[2 * WidthFactor];
141
142
143
144 RopePieceBTreeLeaf **PrevLeaf = nullptr;
145 RopePieceBTreeLeaf *NextLeaf = nullptr;
146
147public:
148 RopePieceBTreeLeaf() : RopePieceBTreeNode(true) {}
149
150 ~RopePieceBTreeLeaf() {
151 if (PrevLeaf || NextLeaf)
152 removeFromLeafInOrder();
153 clear();
154 }
155
156 bool isFull() const { return NumPieces == 2 * WidthFactor; }
157
158
159 void clear() {
160 while (NumPieces)
161 Pieces[--NumPieces] = RopePiece();
163 }
164
165 unsigned getNumPieces() const { return NumPieces; }
166
167 const RopePiece &getPiece(unsigned i) const {
168 assert(i < getNumPieces() && "Invalid piece ID");
169 return Pieces[i];
170 }
171
172 const RopePieceBTreeLeaf *getNextLeafInOrder() const { return NextLeaf; }
173
174 void insertAfterLeafInOrder(RopePieceBTreeLeaf *Node) {
175 assert(!PrevLeaf && !NextLeaf && "Already in ordering");
176
177 NextLeaf = Node->NextLeaf;
178 if (NextLeaf)
179 NextLeaf->PrevLeaf = &NextLeaf;
180 PrevLeaf = &Node->NextLeaf;
181 Node->NextLeaf = this;
182 }
183
184 void removeFromLeafInOrder() {
185 if (PrevLeaf) {
186 *PrevLeaf = NextLeaf;
187 if (NextLeaf)
188 NextLeaf->PrevLeaf = PrevLeaf;
189 } else if (NextLeaf) {
190 NextLeaf->PrevLeaf = nullptr;
191 }
192 }
193
194
195
196 void FullRecomputeSizeLocally() {
198 for (unsigned i = 0, e = getNumPieces(); i != e; ++i)
199 Size += getPiece(i).size();
200 }
201
202
203
204
205
206
207
208 RopePieceBTreeNode *split(unsigned Offset);
209
210
211
212
213
214
215
216 RopePieceBTreeNode *insert(unsigned Offset, const RopePiece &R);
217
218
219
220 void erase(unsigned Offset, unsigned NumBytes);
221
222 static bool classof(const RopePieceBTreeNode *N) { return N->isLeaf(); }
223};
224
225}
226
227
228
229
230
231
232
233RopePieceBTreeNode *RopePieceBTreeLeaf::split(unsigned Offset) {
234
235
237
238 return nullptr;
239 }
240
241
242 unsigned PieceOffs = 0;
243 unsigned i = 0;
244 while (Offset >= PieceOffs + Pieces[i].size()) {
245 PieceOffs += Pieces[i].size();
246 ++i;
247 }
248
249
250
251 if (PieceOffs == Offset)
252 return nullptr;
253
254
255
256 unsigned IntraPieceOffset = Offset - PieceOffs;
257
258
259 RopePiece Tail(Pieces[i].StrData, Pieces[i].StartOffs + IntraPieceOffset,
260 Pieces[i].EndOffs);
264
266}
267
268
269
270
271
272
273RopePieceBTreeNode *RopePieceBTreeLeaf::insert(unsigned Offset,
274 const RopePiece &R) {
275
276 if (!isFull()) {
277
278
279 unsigned i = 0, e = getNumPieces();
281
282 i = e;
283 } else {
284 unsigned SlotOffs = 0;
285 for (; Offset > SlotOffs; ++i)
286 SlotOffs += getPiece(i).size();
287 assert(SlotOffs == Offset && "Split didn't occur before insertion!");
288 }
289
290
291
293 Pieces[e] = Pieces[e - 1];
294 Pieces[i] = R;
295 ++NumPieces;
297 return nullptr;
298 }
299
300
301
302
303
304
305
306 RopePieceBTreeLeaf *NewNode = new RopePieceBTreeLeaf();
307
308
309 std::copy(&Pieces[WidthFactor], &Pieces[2 * WidthFactor],
310 &NewNode->Pieces[0]);
311
312 std::fill(&Pieces[WidthFactor], &Pieces[2 * WidthFactor], RopePiece());
313
314
315 NewNode->NumPieces = NumPieces = WidthFactor;
316
317
318 NewNode->FullRecomputeSizeLocally();
319 FullRecomputeSizeLocally();
320
321
322 NewNode->insertAfterLeafInOrder(this);
323
324
326 this->insert(Offset, R);
327 else
328 NewNode->insert(Offset - this->size(), R);
329 return NewNode;
330}
331
332
333
334void RopePieceBTreeLeaf::erase(unsigned Offset, unsigned NumBytes) {
335
336
337 unsigned PieceOffs = 0;
338 unsigned i = 0;
339 for (; Offset > PieceOffs; ++i)
340 PieceOffs += getPiece(i).size();
341 assert(PieceOffs == Offset && "Split didn't occur before erase!");
342
343 unsigned StartPiece = i;
344
345
346
347 for (; Offset + NumBytes > PieceOffs + getPiece(i).size(); ++i)
348 PieceOffs += getPiece(i).size();
349
350
351 if (Offset + NumBytes == PieceOffs + getPiece(i).size()) {
352 PieceOffs += getPiece(i).size();
353 ++i;
354 }
355
356
357 if (i != StartPiece) {
358 unsigned NumDeleted = i - StartPiece;
359 for (; i != getNumPieces(); ++i)
360 Pieces[i - NumDeleted] = Pieces[i];
361
362
363 std::fill(&Pieces[getNumPieces() - NumDeleted], &Pieces[getNumPieces()],
364 RopePiece());
365 NumPieces -= NumDeleted;
366
367 unsigned CoverBytes = PieceOffs - Offset;
368 NumBytes -= CoverBytes;
369 Size -= CoverBytes;
370 }
371
372
373 if (NumBytes == 0)
374 return;
375
376
377
378 assert(getPiece(StartPiece).size() > NumBytes);
379 Pieces[StartPiece].StartOffs += NumBytes;
380
381
382 Size -= NumBytes;
383}
384
385
386
387
388
389namespace {
390
391
392
393class RopePieceBTreeInterior : public RopePieceBTreeNode {
394
395
396 unsigned char NumChildren = 0;
397
398 RopePieceBTreeNode *Children[2 * WidthFactor];
399
400public:
401 RopePieceBTreeInterior() : RopePieceBTreeNode(false) {}
402
403 RopePieceBTreeInterior(RopePieceBTreeNode *LHS, RopePieceBTreeNode *RHS)
404 : RopePieceBTreeNode(false) {
407 NumChildren = 2;
409 }
410
411 ~RopePieceBTreeInterior() {
412 for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
413 Children[i]->Destroy();
414 }
415
416 bool isFull() const { return NumChildren == 2 * WidthFactor; }
417
418 unsigned getNumChildren() const { return NumChildren; }
419
420 const RopePieceBTreeNode *getChild(unsigned i) const {
421 assert(i < NumChildren && "invalid child #");
423 }
424
425 RopePieceBTreeNode *getChild(unsigned i) {
426 assert(i < NumChildren && "invalid child #");
428 }
429
430
431
432 void FullRecomputeSizeLocally() {
434 for (unsigned i = 0, e = getNumChildren(); i != e; ++i)
435 Size += getChild(i)->size();
436 }
437
438
439
440
441
442
443
444 RopePieceBTreeNode *split(unsigned Offset);
445
446
447
448
449
450
451
452 RopePieceBTreeNode *insert(unsigned Offset, const RopePiece &R);
453
454
455
456 RopePieceBTreeNode *HandleChildPiece(unsigned i, RopePieceBTreeNode *RHS);
457
458
459
460 void erase(unsigned Offset, unsigned NumBytes);
461
462 static bool classof(const RopePieceBTreeNode *N) { return ->isLeaf(); }
463};
464
465}
466
467
468
469
470
471
472
473RopePieceBTreeNode *RopePieceBTreeInterior::split(unsigned Offset) {
474
476 return nullptr;
477
478 unsigned ChildOffset = 0;
479 unsigned i = 0;
480 for (; Offset >= ChildOffset + getChild(i)->size(); ++i)
481 ChildOffset += getChild(i)->size();
482
483
484 if (ChildOffset == Offset)
485 return nullptr;
486
487
488 if (RopePieceBTreeNode *RHS = getChild(i)->split(Offset - ChildOffset))
489 return HandleChildPiece(i, RHS);
490 return nullptr;
491}
492
493
494
495
496
497
498
499RopePieceBTreeNode *RopePieceBTreeInterior::insert(unsigned Offset,
500 const RopePiece &R) {
501
502
503 unsigned i = 0, e = getNumChildren();
504
505 unsigned ChildOffs = 0;
507
508 i = e - 1;
509 ChildOffs = size() - getChild(i)->size();
510 } else {
511 for (; Offset > ChildOffs + getChild(i)->size(); ++i)
512 ChildOffs += getChild(i)->size();
513 }
514
516
517
518 if (RopePieceBTreeNode *RHS = getChild(i)->insert(Offset - ChildOffs, R))
519 return HandleChildPiece(i, RHS);
520
521 return nullptr;
522}
523
524
525
526RopePieceBTreeNode *
527RopePieceBTreeInterior::HandleChildPiece(unsigned i, RopePieceBTreeNode *RHS) {
528
529
530 if (!isFull()) {
531
532 if (i + 1 != getNumChildren())
533 memmove(&Children[i + 2], &Children[i + 1],
534 (getNumChildren() - i - 1) * sizeof(Children[0]));
536 ++NumChildren;
537 return nullptr;
538 }
539
540
541
542
543
544 RopePieceBTreeInterior *NewNode = new RopePieceBTreeInterior();
545
546
547 memcpy(&NewNode->Children[0], &Children[WidthFactor],
548 WidthFactor * sizeof(Children[0]));
549
550
551 NewNode->NumChildren = NumChildren = WidthFactor;
552
553
554
555 if (i < WidthFactor)
556 this->HandleChildPiece(i, RHS);
557 else
558 NewNode->HandleChildPiece(i - WidthFactor, RHS);
559
560
561 NewNode->FullRecomputeSizeLocally();
562 FullRecomputeSizeLocally();
563 return NewNode;
564}
565
566
567
568void RopePieceBTreeInterior::erase(unsigned Offset, unsigned NumBytes) {
569
570 Size -= NumBytes;
571
572
573 unsigned i = 0;
574 for (; Offset >= getChild(i)->size(); ++i)
575 Offset -= getChild(i)->size();
576
577
578
579 while (NumBytes) {
580 RopePieceBTreeNode *CurChild = getChild(i);
581
582
583
584 if (Offset + NumBytes < CurChild->size()) {
585 CurChild->erase(Offset, NumBytes);
586 return;
587 }
588
589
590
592 unsigned BytesFromChild = CurChild->size() - Offset;
593 CurChild->erase(Offset, BytesFromChild);
594 NumBytes -= BytesFromChild;
595
597 ++i;
598 continue;
599 }
600
601
602
603 NumBytes -= CurChild->size();
604 CurChild->Destroy();
605 --NumChildren;
606 if (i != getNumChildren())
607 memmove(&Children[i], &Children[i + 1],
608 (getNumChildren() - i) * sizeof(Children[0]));
609 }
610}
611
612
613
614
615
616void RopePieceBTreeNode::Destroy() {
618 delete Leaf;
619 else
621}
622
623
624
625
626
627
628
629RopePieceBTreeNode *RopePieceBTreeNode::split(unsigned Offset) {
632 return Leaf->split(Offset);
634}
635
636
637
638
639
640
641
642RopePieceBTreeNode *RopePieceBTreeNode::insert(unsigned Offset,
643 const RopePiece &R) {
646 return Leaf->insert(Offset, R);
648}
649
650
651
652void RopePieceBTreeNode::erase(unsigned Offset, unsigned NumBytes) {
653 assert(Offset + NumBytes <= size() && "Invalid offset to erase!");
655 return Leaf->erase(Offset, NumBytes);
657}
658
659
660
661
662
663static const RopePieceBTreeLeaf *getCN(const void *P) {
664 return static_cast<const RopePieceBTreeLeaf *>(P);
665}
666
667
669 const auto *N = static_cast<const RopePieceBTreeNode *>(n);
670
671
673 N = IN->getChild(0);
674
675
677
678
679
680 while (CurNode && getCN(CurNode)->getNumPieces() == 0)
681 CurNode = getCN(CurNode)->getNextLeafInOrder();
682
683 if (CurNode)
684 CurPiece = &getCN(CurNode)->getPiece(0);
685 else
686 CurPiece = nullptr;
687 CurChar = 0;
688}
689
691 if (CurPiece !=
692 &getCN(CurNode)->getPiece(getCN(CurNode)->getNumPieces() - 1)) {
693 CurChar = 0;
694 ++CurPiece;
695 return;
696 }
697
698
699 do
700 CurNode = getCN(CurNode)->getNextLeafInOrder();
701 while (CurNode && getCN(CurNode)->getNumPieces() == 0);
702
703 if (CurNode)
704 CurPiece = &getCN(CurNode)->getPiece(0);
705 else
706 CurPiece = nullptr;
707 CurChar = 0;
708}
709
710
711
712
713
714static RopePieceBTreeNode *getRoot(void *P) {
715 return static_cast<RopePieceBTreeNode *>(P);
716}
717
719
721 assert(RHS.empty() && "Can't copy non-empty tree yet");
722 Root = new RopePieceBTreeLeaf();
723}
724
726
728
731 Leaf->clear();
732 else {
733 getRoot(Root)->Destroy();
734 Root = new RopePieceBTreeLeaf();
735 }
736}
737
739
741 Root = new RopePieceBTreeInterior(getRoot(Root), RHS);
742
743
745 Root = new RopePieceBTreeInterior(getRoot(Root), RHS);
746}
747
749
751 Root = new RopePieceBTreeInterior(getRoot(Root), RHS);
752
753
755}
756
757
758
759
760
761
762
763
764
765RopePiece RewriteRope::MakeRopeString(const char *Start, const char *End) {
766 unsigned Len = End - Start;
767 assert(Len && "Zero length RopePiece is invalid!");
768
769
770 if (AllocOffs + Len <= AllocChunkSize) {
771 memcpy(AllocBuffer->Data + AllocOffs, Start, Len);
772 AllocOffs += Len;
773 return RopePiece(AllocBuffer, AllocOffs - Len, AllocOffs);
774 }
775
776
777
778 if (Len > AllocChunkSize) {
782 memcpy(Res->Data, Start, End - Start);
783 return RopePiece(Res, 0, End - Start);
784 }
785
786
787
788
789 unsigned AllocSize = offsetof(RopeRefCountString, Data) + AllocChunkSize;
790 auto *Res = reinterpret_cast<RopeRefCountString *>(new char[AllocSize]);
791 Res->RefCount = 0;
792 memcpy(Res->Data, Start, Len);
793 AllocBuffer = Res;
794 AllocOffs = Len;
795
796 return RopePiece(AllocBuffer, 0, Len);
797}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Function Alias Analysis false
static DeltaTreeNode * getRoot(void *Root)
#define offsetof(TYPE, MEMBER)
static const RopePieceBTreeLeaf * getCN(const void *P)
Definition RewriteRope.cpp:663
RopePieceBTreeIterator()=default
LLVM_ABI void MoveToNextPiece()
Definition RewriteRope.cpp:690
LLVM_ABI ~RopePieceBTree()
Definition RewriteRope.cpp:725
LLVM_ABI unsigned size() const
Definition RewriteRope.cpp:727
LLVM_ABI void insert(unsigned Offset, const RopePiece &R)
Definition RewriteRope.cpp:738
LLVM_ABI void erase(unsigned Offset, unsigned NumBytes)
Definition RewriteRope.cpp:748
LLVM_ABI void clear()
Definition RewriteRope.cpp:729
LLVM_ABI RopePieceBTree()
Definition RewriteRope.cpp:718
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
decltype(auto) dyn_cast(const From &Val)
dyn_cast - Return the argument parameter cast to the specified type.
void erase(Container &C, ValueType V)
Wrapper function to remove a value from a container:
iterator_range< SplittingIterator > split(StringRef Str, StringRef Separator)
Split the specified string over a separator and return a range-compatible iterable over its partition...
FunctionAddr VTableAddr uintptr_t uintptr_t Data
decltype(auto) cast(const From &Val)
cast - Return the argument parameter cast to the specified type.
RopePiece - This class represents a view into a RopeRefCountString object.
RopeRefCountString - This struct is allocated with 'new char[]' from the heap, and represents a refer...