15#include "llvm/Support/Casting.h"
45 static SourceDelta get(
unsigned Loc,
int D) {
58 DeltaTreeNode *LHS, *RHS;
63 friend class DeltaTreeInteriorNode;
69 enum { WidthFactor = 8 };
72 SourceDelta Values[2*WidthFactor-1];
76 unsigned char NumValuesUsed = 0;
87 DeltaTreeNode(
bool isLeaf =
true) : IsLeaf(isLeaf) {}
89 bool isLeaf()
const {
return IsLeaf; }
90 int getFullDelta()
const {
return FullDelta; }
91 bool isFull()
const {
return NumValuesUsed == 2*WidthFactor-1; }
93 unsigned getNumValuesUsed()
const {
return NumValuesUsed; }
95 const SourceDelta &getValue(
unsigned i)
const {
96 assert(i < NumValuesUsed &&
"Invalid value #");
100 SourceDelta &getValue(
unsigned i) {
101 assert(i < NumValuesUsed &&
"Invalid value #");
109 bool DoInsertion(
unsigned FileIndex,
int Delta, InsertResult *InsertRes);
111 void DoSplit(InsertResult &InsertRes);
116 void RecomputeFullDeltaLocally();
123 class DeltaTreeInteriorNode :
public DeltaTreeNode {
124 friend class DeltaTreeNode;
126 DeltaTreeNode *Children[2*WidthFactor];
128 ~DeltaTreeInteriorNode() {
129 for (
unsigned i = 0, e = NumValuesUsed+1; i != e; ++i)
134 DeltaTreeInteriorNode() : DeltaTreeNode(
false ) {}
136 DeltaTreeInteriorNode(
const InsertResult &IR)
137 : DeltaTreeNode(
false ) {
138 Children[0] = IR.LHS;
139 Children[1] = IR.RHS;
140 Values[0] = IR.Split;
141 FullDelta = IR.LHS->getFullDelta()+IR.RHS->getFullDelta()+IR.Split.Delta;
145 const DeltaTreeNode *getChild(
unsigned i)
const {
146 assert(i < getNumValuesUsed()+1 &&
"Invalid child");
150 DeltaTreeNode *getChild(
unsigned i) {
151 assert(i < getNumValuesUsed()+1 &&
"Invalid child");
155 static bool classof(
const DeltaTreeNode *N) {
return !N->isLeaf(); }
161void DeltaTreeNode::Destroy() {
165 delete cast<DeltaTreeInteriorNode>(
this);
170void DeltaTreeNode::RecomputeFullDeltaLocally() {
171 int NewFullDelta = 0;
172 for (
unsigned i = 0, e = getNumValuesUsed(); i != e; ++i)
173 NewFullDelta += Values[i].Delta;
174 if (
auto *IN = dyn_cast<DeltaTreeInteriorNode>(
this))
175 for (
unsigned i = 0, e = getNumValuesUsed()+1; i != e; ++i)
176 NewFullDelta += IN->getChild(i)->getFullDelta();
177 FullDelta = NewFullDelta;
184bool DeltaTreeNode::DoInsertion(
unsigned FileIndex,
int Delta,
185 InsertResult *InsertRes) {
190 unsigned i = 0, e = getNumValuesUsed();
191 while (i != e && FileIndex > getValue(i).FileLoc)
196 if (i != e && getValue(i).FileLoc == FileIndex) {
201 Values[i].Delta += Delta;
212 memmove(&Values[i+1], &Values[i],
sizeof(Values[0])*(e-i));
213 Values[i] = SourceDelta::get(FileIndex, Delta);
220 assert(InsertRes &&
"No result location specified");
223 if (InsertRes->Split.FileLoc > FileIndex)
224 InsertRes->LHS->DoInsertion(FileIndex, Delta,
nullptr );
226 InsertRes->RHS->DoInsertion(FileIndex, Delta,
nullptr );
231 auto *IN = cast<DeltaTreeInteriorNode>(
this);
232 if (!IN->Children[i]->DoInsertion(FileIndex, Delta, InsertRes))
242 memmove(&IN->Children[i+2], &IN->Children[i+1],
243 (e-i)*
sizeof(IN->Children[0]));
244 IN->Children[i] = InsertRes->LHS;
245 IN->Children[i+1] = InsertRes->RHS;
248 memmove(&Values[i+1], &Values[i], (e-i)*
sizeof(Values[0]));
249 Values[i] = InsertRes->Split;
257 IN->Children[i] = InsertRes->LHS;
258 DeltaTreeNode *SubRHS = InsertRes->RHS;
259 SourceDelta SubSplit = InsertRes->Split;
265 DeltaTreeInteriorNode *InsertSide;
266 if (SubSplit.FileLoc < InsertRes->Split.FileLoc)
267 InsertSide = cast<DeltaTreeInteriorNode>(InsertRes->LHS);
269 InsertSide = cast<DeltaTreeInteriorNode>(InsertRes->RHS);
275 i = 0; e = InsertSide->getNumValuesUsed();
276 while (i != e && SubSplit.FileLoc > InsertSide->getValue(i).FileLoc)
282 memmove(&InsertSide->Children[i+2], &InsertSide->Children[i+1],
283 (e-i)*
sizeof(IN->Children[0]));
284 InsertSide->Children[i+1] = SubRHS;
287 memmove(&InsertSide->Values[i+1], &InsertSide->Values[i],
288 (e-i)*
sizeof(Values[0]));
289 InsertSide->Values[i] = SubSplit;
290 ++InsertSide->NumValuesUsed;
291 InsertSide->FullDelta += SubSplit.Delta + SubRHS->getFullDelta();
298void DeltaTreeNode::DoSplit(InsertResult &InsertRes) {
299 assert(isFull() &&
"Why split a non-full node?");
307 DeltaTreeNode *NewNode;
308 if (
auto *IN = dyn_cast<DeltaTreeInteriorNode>(
this)) {
311 DeltaTreeInteriorNode *New =
new DeltaTreeInteriorNode();
312 memcpy(&New->Children[0], &IN->Children[WidthFactor],
313 WidthFactor*
sizeof(IN->Children[0]));
317 NewNode =
new DeltaTreeNode();
321 memcpy(&NewNode->Values[0], &Values[WidthFactor],
322 (WidthFactor-1)*
sizeof(Values[0]));
325 NewNode->NumValuesUsed = NumValuesUsed = WidthFactor-1;
328 NewNode->RecomputeFullDeltaLocally();
329 RecomputeFullDeltaLocally();
331 InsertRes.LHS =
this;
332 InsertRes.RHS = NewNode;
333 InsertRes.Split = Values[WidthFactor-1];
345static void VerifyTree(
const DeltaTreeNode *N) {
346 const auto *IN = dyn_cast<DeltaTreeInteriorNode>(N);
351 for (
unsigned i = 0, e = N->getNumValuesUsed(); i != e; ++i) {
353 assert(N->getValue(i-1).FileLoc < N->getValue(i).FileLoc);
354 FullDelta += N->getValue(i).Delta;
356 assert(FullDelta == N->getFullDelta());
363 for (
unsigned i = 0, e = IN->getNumValuesUsed(); i != e; ++i) {
364 const SourceDelta &IVal = N->getValue(i);
365 const DeltaTreeNode *IChild = IN->getChild(i);
367 assert(IN->getValue(i-1).FileLoc < IVal.FileLoc);
368 FullDelta += IVal.Delta;
369 FullDelta += IChild->getFullDelta();
372 assert(IChild->getValue(IChild->getNumValuesUsed()-1).FileLoc <
376 assert(IN->getChild(i+1)->getValue(0).FileLoc > IVal.FileLoc);
380 FullDelta += IN->getChild(IN->getNumValuesUsed())->getFullDelta();
382 assert(FullDelta == N->getFullDelta());
387 return (DeltaTreeNode*)Root;
391 Root =
new DeltaTreeNode();
396 assert(
getRoot(RHS.Root)->getNumValuesUsed() == 0 &&
397 "Can only copy empty tree");
398 Root =
new DeltaTreeNode();
418 unsigned NumValsGreater = 0;
419 for (
unsigned e =
Node->getNumValuesUsed(); NumValsGreater != e;
421 const SourceDelta &Val =
Node->getValue(NumValsGreater);
423 if (Val.FileLoc >= FileIndex)
430 const auto *IN = dyn_cast<DeltaTreeInteriorNode>(
Node);
435 for (
unsigned i = 0; i != NumValsGreater; ++i)
436 Result += IN->getChild(i)->getFullDelta();
441 if (NumValsGreater !=
Node->getNumValuesUsed() &&
442 Node->getValue(NumValsGreater).FileLoc == FileIndex)
443 return Result+IN->getChild(NumValsGreater)->getFullDelta();
447 Node = IN->getChild(NumValsGreater);
456 assert(Delta &&
"Adding a noop?");
457 DeltaTreeNode *MyRoot =
getRoot(Root);
459 DeltaTreeNode::InsertResult InsertRes;
460 if (MyRoot->DoInsertion(FileIndex, Delta, &InsertRes)) {
461 Root =
new DeltaTreeInteriorNode(InsertRes);
static DeltaTreeNode * getRoot(void *Root)
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
DeltaTree - a multiway search tree (BTree) structure with some fancy features.
void AddDelta(unsigned FileIndex, int Delta)
AddDelta - When a change is made that shifts around the text buffer, this method is used to record th...
int getDeltaAt(unsigned FileIndex) const
getDeltaAt - Return the accumulated delta at the specified file offset.
bool Destroy(InterpState &S, CodePtr OpPC, uint32_t I)
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.