xref: /freebsd-src/contrib/llvm-project/clang/lib/Rewrite/DeltaTree.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
10b57cec5SDimitry Andric //===- DeltaTree.cpp - B-Tree for Rewrite Delta tracking ------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the DeltaTree and related classes.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "clang/Rewrite/Core/DeltaTree.h"
140b57cec5SDimitry Andric #include "clang/Basic/LLVM.h"
150b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
160b57cec5SDimitry Andric #include <cassert>
170b57cec5SDimitry Andric #include <cstring>
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric using namespace clang;
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric /// The DeltaTree class is a multiway search tree (BTree) structure with some
220b57cec5SDimitry Andric /// fancy features.  B-Trees are generally more memory and cache efficient
230b57cec5SDimitry Andric /// than binary trees, because they store multiple keys/values in each node.
240b57cec5SDimitry Andric ///
250b57cec5SDimitry Andric /// DeltaTree implements a key/value mapping from FileIndex to Delta, allowing
260b57cec5SDimitry Andric /// fast lookup by FileIndex.  However, an added (important) bonus is that it
270b57cec5SDimitry Andric /// can also efficiently tell us the full accumulated delta for a specific
280b57cec5SDimitry Andric /// file offset as well, without traversing the whole tree.
290b57cec5SDimitry Andric ///
300b57cec5SDimitry Andric /// The nodes of the tree are made up of instances of two classes:
310b57cec5SDimitry Andric /// DeltaTreeNode and DeltaTreeInteriorNode.  The later subclasses the
320b57cec5SDimitry Andric /// former and adds children pointers.  Each node knows the full delta of all
330b57cec5SDimitry Andric /// entries (recursively) contained inside of it, which allows us to get the
340b57cec5SDimitry Andric /// full delta implied by a whole subtree in constant time.
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric namespace {
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric   /// SourceDelta - As code in the original input buffer is added and deleted,
390b57cec5SDimitry Andric   /// SourceDelta records are used to keep track of how the input SourceLocation
400b57cec5SDimitry Andric   /// object is mapped into the output buffer.
410b57cec5SDimitry Andric   struct SourceDelta {
420b57cec5SDimitry Andric     unsigned FileLoc;
430b57cec5SDimitry Andric     int Delta;
440b57cec5SDimitry Andric 
get__anon9d934e970111::SourceDelta450b57cec5SDimitry Andric     static SourceDelta get(unsigned Loc, int D) {
460b57cec5SDimitry Andric       SourceDelta Delta;
470b57cec5SDimitry Andric       Delta.FileLoc = Loc;
480b57cec5SDimitry Andric       Delta.Delta = D;
490b57cec5SDimitry Andric       return Delta;
500b57cec5SDimitry Andric     }
510b57cec5SDimitry Andric   };
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   /// DeltaTreeNode - The common part of all nodes.
540b57cec5SDimitry Andric   ///
550b57cec5SDimitry Andric   class DeltaTreeNode {
560b57cec5SDimitry Andric   public:
570b57cec5SDimitry Andric     struct InsertResult {
580b57cec5SDimitry Andric       DeltaTreeNode *LHS, *RHS;
590b57cec5SDimitry Andric       SourceDelta Split;
600b57cec5SDimitry Andric     };
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric   private:
630b57cec5SDimitry Andric     friend class DeltaTreeInteriorNode;
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric     /// WidthFactor - This controls the number of K/V slots held in the BTree:
660b57cec5SDimitry Andric     /// how wide it is.  Each level of the BTree is guaranteed to have at least
670b57cec5SDimitry Andric     /// WidthFactor-1 K/V pairs (except the root) and may have at most
680b57cec5SDimitry Andric     /// 2*WidthFactor-1 K/V pairs.
690b57cec5SDimitry Andric     enum { WidthFactor = 8 };
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric     /// Values - This tracks the SourceDelta's currently in this node.
720b57cec5SDimitry Andric     SourceDelta Values[2*WidthFactor-1];
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric     /// NumValuesUsed - This tracks the number of values this node currently
750b57cec5SDimitry Andric     /// holds.
760b57cec5SDimitry Andric     unsigned char NumValuesUsed = 0;
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric     /// IsLeaf - This is true if this is a leaf of the btree.  If false, this is
790b57cec5SDimitry Andric     /// an interior node, and is actually an instance of DeltaTreeInteriorNode.
800b57cec5SDimitry Andric     bool IsLeaf;
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric     /// FullDelta - This is the full delta of all the values in this node and
830b57cec5SDimitry Andric     /// all children nodes.
840b57cec5SDimitry Andric     int FullDelta = 0;
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   public:
DeltaTreeNode(bool isLeaf=true)870b57cec5SDimitry Andric     DeltaTreeNode(bool isLeaf = true) : IsLeaf(isLeaf) {}
880b57cec5SDimitry Andric 
isLeaf() const890b57cec5SDimitry Andric     bool isLeaf() const { return IsLeaf; }
getFullDelta() const900b57cec5SDimitry Andric     int getFullDelta() const { return FullDelta; }
isFull() const910b57cec5SDimitry Andric     bool isFull() const { return NumValuesUsed == 2*WidthFactor-1; }
920b57cec5SDimitry Andric 
getNumValuesUsed() const930b57cec5SDimitry Andric     unsigned getNumValuesUsed() const { return NumValuesUsed; }
940b57cec5SDimitry Andric 
getValue(unsigned i) const950b57cec5SDimitry Andric     const SourceDelta &getValue(unsigned i) const {
960b57cec5SDimitry Andric       assert(i < NumValuesUsed && "Invalid value #");
970b57cec5SDimitry Andric       return Values[i];
980b57cec5SDimitry Andric     }
990b57cec5SDimitry Andric 
getValue(unsigned i)1000b57cec5SDimitry Andric     SourceDelta &getValue(unsigned i) {
1010b57cec5SDimitry Andric       assert(i < NumValuesUsed && "Invalid value #");
1020b57cec5SDimitry Andric       return Values[i];
1030b57cec5SDimitry Andric     }
1040b57cec5SDimitry Andric 
1050b57cec5SDimitry Andric     /// DoInsertion - Do an insertion of the specified FileIndex/Delta pair into
1060b57cec5SDimitry Andric     /// this node.  If insertion is easy, do it and return false.  Otherwise,
1070b57cec5SDimitry Andric     /// split the node, populate InsertRes with info about the split, and return
1080b57cec5SDimitry Andric     /// true.
1090b57cec5SDimitry Andric     bool DoInsertion(unsigned FileIndex, int Delta, InsertResult *InsertRes);
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric     void DoSplit(InsertResult &InsertRes);
1120b57cec5SDimitry Andric 
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric     /// RecomputeFullDeltaLocally - Recompute the FullDelta field by doing a
1150b57cec5SDimitry Andric     /// local walk over our contained deltas.
1160b57cec5SDimitry Andric     void RecomputeFullDeltaLocally();
1170b57cec5SDimitry Andric 
1180b57cec5SDimitry Andric     void Destroy();
1190b57cec5SDimitry Andric   };
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric   /// DeltaTreeInteriorNode - When isLeaf = false, a node has child pointers.
1220b57cec5SDimitry Andric   /// This class tracks them.
1230b57cec5SDimitry Andric   class DeltaTreeInteriorNode : public DeltaTreeNode {
1240b57cec5SDimitry Andric     friend class DeltaTreeNode;
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric     DeltaTreeNode *Children[2*WidthFactor];
1270b57cec5SDimitry Andric 
~DeltaTreeInteriorNode()1280b57cec5SDimitry Andric     ~DeltaTreeInteriorNode() {
1290b57cec5SDimitry Andric       for (unsigned i = 0, e = NumValuesUsed+1; i != e; ++i)
1300b57cec5SDimitry Andric         Children[i]->Destroy();
1310b57cec5SDimitry Andric     }
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric   public:
DeltaTreeInteriorNode()1340b57cec5SDimitry Andric     DeltaTreeInteriorNode() : DeltaTreeNode(false /*nonleaf*/) {}
1350b57cec5SDimitry Andric 
DeltaTreeInteriorNode(const InsertResult & IR)1360b57cec5SDimitry Andric     DeltaTreeInteriorNode(const InsertResult &IR)
1370b57cec5SDimitry Andric         : DeltaTreeNode(false /*nonleaf*/) {
1380b57cec5SDimitry Andric       Children[0] = IR.LHS;
1390b57cec5SDimitry Andric       Children[1] = IR.RHS;
1400b57cec5SDimitry Andric       Values[0] = IR.Split;
1410b57cec5SDimitry Andric       FullDelta = IR.LHS->getFullDelta()+IR.RHS->getFullDelta()+IR.Split.Delta;
1420b57cec5SDimitry Andric       NumValuesUsed = 1;
1430b57cec5SDimitry Andric     }
1440b57cec5SDimitry Andric 
getChild(unsigned i) const1450b57cec5SDimitry Andric     const DeltaTreeNode *getChild(unsigned i) const {
1460b57cec5SDimitry Andric       assert(i < getNumValuesUsed()+1 && "Invalid child");
1470b57cec5SDimitry Andric       return Children[i];
1480b57cec5SDimitry Andric     }
1490b57cec5SDimitry Andric 
getChild(unsigned i)1500b57cec5SDimitry Andric     DeltaTreeNode *getChild(unsigned i) {
1510b57cec5SDimitry Andric       assert(i < getNumValuesUsed()+1 && "Invalid child");
1520b57cec5SDimitry Andric       return Children[i];
1530b57cec5SDimitry Andric     }
1540b57cec5SDimitry Andric 
classof(const DeltaTreeNode * N)1550b57cec5SDimitry Andric     static bool classof(const DeltaTreeNode *N) { return !N->isLeaf(); }
1560b57cec5SDimitry Andric   };
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric } // namespace
1590b57cec5SDimitry Andric 
1600b57cec5SDimitry Andric /// Destroy - A 'virtual' destructor.
Destroy()1610b57cec5SDimitry Andric void DeltaTreeNode::Destroy() {
1620b57cec5SDimitry Andric   if (isLeaf())
1630b57cec5SDimitry Andric     delete this;
1640b57cec5SDimitry Andric   else
1650b57cec5SDimitry Andric     delete cast<DeltaTreeInteriorNode>(this);
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric /// RecomputeFullDeltaLocally - Recompute the FullDelta field by doing a
1690b57cec5SDimitry Andric /// local walk over our contained deltas.
RecomputeFullDeltaLocally()1700b57cec5SDimitry Andric void DeltaTreeNode::RecomputeFullDeltaLocally() {
1710b57cec5SDimitry Andric   int NewFullDelta = 0;
1720b57cec5SDimitry Andric   for (unsigned i = 0, e = getNumValuesUsed(); i != e; ++i)
1730b57cec5SDimitry Andric     NewFullDelta += Values[i].Delta;
1740b57cec5SDimitry Andric   if (auto *IN = dyn_cast<DeltaTreeInteriorNode>(this))
1750b57cec5SDimitry Andric     for (unsigned i = 0, e = getNumValuesUsed()+1; i != e; ++i)
1760b57cec5SDimitry Andric       NewFullDelta += IN->getChild(i)->getFullDelta();
1770b57cec5SDimitry Andric   FullDelta = NewFullDelta;
1780b57cec5SDimitry Andric }
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric /// DoInsertion - Do an insertion of the specified FileIndex/Delta pair into
1810b57cec5SDimitry Andric /// this node.  If insertion is easy, do it and return false.  Otherwise,
1820b57cec5SDimitry Andric /// split the node, populate InsertRes with info about the split, and return
1830b57cec5SDimitry Andric /// true.
DoInsertion(unsigned FileIndex,int Delta,InsertResult * InsertRes)1840b57cec5SDimitry Andric bool DeltaTreeNode::DoInsertion(unsigned FileIndex, int Delta,
1850b57cec5SDimitry Andric                                 InsertResult *InsertRes) {
1860b57cec5SDimitry Andric   // Maintain full delta for this node.
1870b57cec5SDimitry Andric   FullDelta += Delta;
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric   // Find the insertion point, the first delta whose index is >= FileIndex.
1900b57cec5SDimitry Andric   unsigned i = 0, e = getNumValuesUsed();
1910b57cec5SDimitry Andric   while (i != e && FileIndex > getValue(i).FileLoc)
1920b57cec5SDimitry Andric     ++i;
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric   // If we found an a record for exactly this file index, just merge this
1950b57cec5SDimitry Andric   // value into the pre-existing record and finish early.
1960b57cec5SDimitry Andric   if (i != e && getValue(i).FileLoc == FileIndex) {
1970b57cec5SDimitry Andric     // NOTE: Delta could drop to zero here.  This means that the delta entry is
1980b57cec5SDimitry Andric     // useless and could be removed.  Supporting erases is more complex than
1990b57cec5SDimitry Andric     // leaving an entry with Delta=0, so we just leave an entry with Delta=0 in
2000b57cec5SDimitry Andric     // the tree.
2010b57cec5SDimitry Andric     Values[i].Delta += Delta;
2020b57cec5SDimitry Andric     return false;
2030b57cec5SDimitry Andric   }
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric   // Otherwise, we found an insertion point, and we know that the value at the
2060b57cec5SDimitry Andric   // specified index is > FileIndex.  Handle the leaf case first.
2070b57cec5SDimitry Andric   if (isLeaf()) {
2080b57cec5SDimitry Andric     if (!isFull()) {
2090b57cec5SDimitry Andric       // For an insertion into a non-full leaf node, just insert the value in
2100b57cec5SDimitry Andric       // its sorted position.  This requires moving later values over.
2110b57cec5SDimitry Andric       if (i != e)
2120b57cec5SDimitry Andric         memmove(&Values[i+1], &Values[i], sizeof(Values[0])*(e-i));
2130b57cec5SDimitry Andric       Values[i] = SourceDelta::get(FileIndex, Delta);
2140b57cec5SDimitry Andric       ++NumValuesUsed;
2150b57cec5SDimitry Andric       return false;
2160b57cec5SDimitry Andric     }
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric     // Otherwise, if this is leaf is full, split the node at its median, insert
2190b57cec5SDimitry Andric     // the value into one of the children, and return the result.
2200b57cec5SDimitry Andric     assert(InsertRes && "No result location specified");
2210b57cec5SDimitry Andric     DoSplit(*InsertRes);
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric     if (InsertRes->Split.FileLoc > FileIndex)
2240b57cec5SDimitry Andric       InsertRes->LHS->DoInsertion(FileIndex, Delta, nullptr /*can't fail*/);
2250b57cec5SDimitry Andric     else
2260b57cec5SDimitry Andric       InsertRes->RHS->DoInsertion(FileIndex, Delta, nullptr /*can't fail*/);
2270b57cec5SDimitry Andric     return true;
2280b57cec5SDimitry Andric   }
2290b57cec5SDimitry Andric 
2300b57cec5SDimitry Andric   // Otherwise, this is an interior node.  Send the request down the tree.
2310b57cec5SDimitry Andric   auto *IN = cast<DeltaTreeInteriorNode>(this);
2320b57cec5SDimitry Andric   if (!IN->Children[i]->DoInsertion(FileIndex, Delta, InsertRes))
2330b57cec5SDimitry Andric     return false; // If there was space in the child, just return.
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric   // Okay, this split the subtree, producing a new value and two children to
2360b57cec5SDimitry Andric   // insert here.  If this node is non-full, we can just insert it directly.
2370b57cec5SDimitry Andric   if (!isFull()) {
2380b57cec5SDimitry Andric     // Now that we have two nodes and a new element, insert the perclated value
2390b57cec5SDimitry Andric     // into ourself by moving all the later values/children down, then inserting
2400b57cec5SDimitry Andric     // the new one.
2410b57cec5SDimitry Andric     if (i != e)
2420b57cec5SDimitry Andric       memmove(&IN->Children[i+2], &IN->Children[i+1],
2430b57cec5SDimitry Andric               (e-i)*sizeof(IN->Children[0]));
2440b57cec5SDimitry Andric     IN->Children[i] = InsertRes->LHS;
2450b57cec5SDimitry Andric     IN->Children[i+1] = InsertRes->RHS;
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric     if (e != i)
2480b57cec5SDimitry Andric       memmove(&Values[i+1], &Values[i], (e-i)*sizeof(Values[0]));
2490b57cec5SDimitry Andric     Values[i] = InsertRes->Split;
2500b57cec5SDimitry Andric     ++NumValuesUsed;
2510b57cec5SDimitry Andric     return false;
2520b57cec5SDimitry Andric   }
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric   // Finally, if this interior node was full and a node is percolated up, split
2550b57cec5SDimitry Andric   // ourself and return that up the chain.  Start by saving all our info to
2560b57cec5SDimitry Andric   // avoid having the split clobber it.
2570b57cec5SDimitry Andric   IN->Children[i] = InsertRes->LHS;
2580b57cec5SDimitry Andric   DeltaTreeNode *SubRHS = InsertRes->RHS;
2590b57cec5SDimitry Andric   SourceDelta SubSplit = InsertRes->Split;
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric   // Do the split.
2620b57cec5SDimitry Andric   DoSplit(*InsertRes);
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric   // Figure out where to insert SubRHS/NewSplit.
2650b57cec5SDimitry Andric   DeltaTreeInteriorNode *InsertSide;
2660b57cec5SDimitry Andric   if (SubSplit.FileLoc < InsertRes->Split.FileLoc)
2670b57cec5SDimitry Andric     InsertSide = cast<DeltaTreeInteriorNode>(InsertRes->LHS);
2680b57cec5SDimitry Andric   else
2690b57cec5SDimitry Andric     InsertSide = cast<DeltaTreeInteriorNode>(InsertRes->RHS);
2700b57cec5SDimitry Andric 
2710b57cec5SDimitry Andric   // We now have a non-empty interior node 'InsertSide' to insert
2720b57cec5SDimitry Andric   // SubRHS/SubSplit into.  Find out where to insert SubSplit.
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric   // Find the insertion point, the first delta whose index is >SubSplit.FileLoc.
2750b57cec5SDimitry Andric   i = 0; e = InsertSide->getNumValuesUsed();
2760b57cec5SDimitry Andric   while (i != e && SubSplit.FileLoc > InsertSide->getValue(i).FileLoc)
2770b57cec5SDimitry Andric     ++i;
2780b57cec5SDimitry Andric 
2790b57cec5SDimitry Andric   // Now we know that i is the place to insert the split value into.  Insert it
2800b57cec5SDimitry Andric   // and the child right after it.
2810b57cec5SDimitry Andric   if (i != e)
2820b57cec5SDimitry Andric     memmove(&InsertSide->Children[i+2], &InsertSide->Children[i+1],
2830b57cec5SDimitry Andric             (e-i)*sizeof(IN->Children[0]));
2840b57cec5SDimitry Andric   InsertSide->Children[i+1] = SubRHS;
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric   if (e != i)
2870b57cec5SDimitry Andric     memmove(&InsertSide->Values[i+1], &InsertSide->Values[i],
2880b57cec5SDimitry Andric             (e-i)*sizeof(Values[0]));
2890b57cec5SDimitry Andric   InsertSide->Values[i] = SubSplit;
2900b57cec5SDimitry Andric   ++InsertSide->NumValuesUsed;
2910b57cec5SDimitry Andric   InsertSide->FullDelta += SubSplit.Delta + SubRHS->getFullDelta();
2920b57cec5SDimitry Andric   return true;
2930b57cec5SDimitry Andric }
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric /// DoSplit - Split the currently full node (which has 2*WidthFactor-1 values)
2960b57cec5SDimitry Andric /// into two subtrees each with "WidthFactor-1" values and a pivot value.
2970b57cec5SDimitry Andric /// Return the pieces in InsertRes.
DoSplit(InsertResult & InsertRes)2980b57cec5SDimitry Andric void DeltaTreeNode::DoSplit(InsertResult &InsertRes) {
2990b57cec5SDimitry Andric   assert(isFull() && "Why split a non-full node?");
3000b57cec5SDimitry Andric 
3010b57cec5SDimitry Andric   // Since this node is full, it contains 2*WidthFactor-1 values.  We move
3020b57cec5SDimitry Andric   // the first 'WidthFactor-1' values to the LHS child (which we leave in this
3030b57cec5SDimitry Andric   // node), propagate one value up, and move the last 'WidthFactor-1' values
3040b57cec5SDimitry Andric   // into the RHS child.
3050b57cec5SDimitry Andric 
3060b57cec5SDimitry Andric   // Create the new child node.
3070b57cec5SDimitry Andric   DeltaTreeNode *NewNode;
3080b57cec5SDimitry Andric   if (auto *IN = dyn_cast<DeltaTreeInteriorNode>(this)) {
3090b57cec5SDimitry Andric     // If this is an interior node, also move over 'WidthFactor' children
3100b57cec5SDimitry Andric     // into the new node.
3110b57cec5SDimitry Andric     DeltaTreeInteriorNode *New = new DeltaTreeInteriorNode();
3120b57cec5SDimitry Andric     memcpy(&New->Children[0], &IN->Children[WidthFactor],
3130b57cec5SDimitry Andric            WidthFactor*sizeof(IN->Children[0]));
3140b57cec5SDimitry Andric     NewNode = New;
3150b57cec5SDimitry Andric   } else {
3160b57cec5SDimitry Andric     // Just create the new leaf node.
3170b57cec5SDimitry Andric     NewNode = new DeltaTreeNode();
3180b57cec5SDimitry Andric   }
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric   // Move over the last 'WidthFactor-1' values from here to NewNode.
3210b57cec5SDimitry Andric   memcpy(&NewNode->Values[0], &Values[WidthFactor],
3220b57cec5SDimitry Andric          (WidthFactor-1)*sizeof(Values[0]));
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric   // Decrease the number of values in the two nodes.
3250b57cec5SDimitry Andric   NewNode->NumValuesUsed = NumValuesUsed = WidthFactor-1;
3260b57cec5SDimitry Andric 
3270b57cec5SDimitry Andric   // Recompute the two nodes' full delta.
3280b57cec5SDimitry Andric   NewNode->RecomputeFullDeltaLocally();
3290b57cec5SDimitry Andric   RecomputeFullDeltaLocally();
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric   InsertRes.LHS = this;
3320b57cec5SDimitry Andric   InsertRes.RHS = NewNode;
3330b57cec5SDimitry Andric   InsertRes.Split = Values[WidthFactor-1];
3340b57cec5SDimitry Andric }
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
3370b57cec5SDimitry Andric //                        DeltaTree Implementation
3380b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
3390b57cec5SDimitry Andric 
3400b57cec5SDimitry Andric //#define VERIFY_TREE
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric #ifdef VERIFY_TREE
3430b57cec5SDimitry Andric /// VerifyTree - Walk the btree performing assertions on various properties to
3440b57cec5SDimitry Andric /// verify consistency.  This is useful for debugging new changes to the tree.
VerifyTree(const DeltaTreeNode * N)3450b57cec5SDimitry Andric static void VerifyTree(const DeltaTreeNode *N) {
3460b57cec5SDimitry Andric   const auto *IN = dyn_cast<DeltaTreeInteriorNode>(N);
3470b57cec5SDimitry Andric   if (IN == 0) {
3480b57cec5SDimitry Andric     // Verify leaves, just ensure that FullDelta matches up and the elements
3490b57cec5SDimitry Andric     // are in proper order.
3500b57cec5SDimitry Andric     int FullDelta = 0;
3510b57cec5SDimitry Andric     for (unsigned i = 0, e = N->getNumValuesUsed(); i != e; ++i) {
3520b57cec5SDimitry Andric       if (i)
3530b57cec5SDimitry Andric         assert(N->getValue(i-1).FileLoc < N->getValue(i).FileLoc);
3540b57cec5SDimitry Andric       FullDelta += N->getValue(i).Delta;
3550b57cec5SDimitry Andric     }
3560b57cec5SDimitry Andric     assert(FullDelta == N->getFullDelta());
3570b57cec5SDimitry Andric     return;
3580b57cec5SDimitry Andric   }
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric   // Verify interior nodes: Ensure that FullDelta matches up and the
3610b57cec5SDimitry Andric   // elements are in proper order and the children are in proper order.
3620b57cec5SDimitry Andric   int FullDelta = 0;
3630b57cec5SDimitry Andric   for (unsigned i = 0, e = IN->getNumValuesUsed(); i != e; ++i) {
3640b57cec5SDimitry Andric     const SourceDelta &IVal = N->getValue(i);
3650b57cec5SDimitry Andric     const DeltaTreeNode *IChild = IN->getChild(i);
3660b57cec5SDimitry Andric     if (i)
3670b57cec5SDimitry Andric       assert(IN->getValue(i-1).FileLoc < IVal.FileLoc);
3680b57cec5SDimitry Andric     FullDelta += IVal.Delta;
3690b57cec5SDimitry Andric     FullDelta += IChild->getFullDelta();
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric     // The largest value in child #i should be smaller than FileLoc.
3720b57cec5SDimitry Andric     assert(IChild->getValue(IChild->getNumValuesUsed()-1).FileLoc <
3730b57cec5SDimitry Andric            IVal.FileLoc);
3740b57cec5SDimitry Andric 
3750b57cec5SDimitry Andric     // The smallest value in child #i+1 should be larger than FileLoc.
3760b57cec5SDimitry Andric     assert(IN->getChild(i+1)->getValue(0).FileLoc > IVal.FileLoc);
3770b57cec5SDimitry Andric     VerifyTree(IChild);
3780b57cec5SDimitry Andric   }
3790b57cec5SDimitry Andric 
3800b57cec5SDimitry Andric   FullDelta += IN->getChild(IN->getNumValuesUsed())->getFullDelta();
3810b57cec5SDimitry Andric 
3820b57cec5SDimitry Andric   assert(FullDelta == N->getFullDelta());
3830b57cec5SDimitry Andric }
3840b57cec5SDimitry Andric #endif  // VERIFY_TREE
3850b57cec5SDimitry Andric 
getRoot(void * Root)3860b57cec5SDimitry Andric static DeltaTreeNode *getRoot(void *Root) {
3870b57cec5SDimitry Andric   return (DeltaTreeNode*)Root;
3880b57cec5SDimitry Andric }
3890b57cec5SDimitry Andric 
DeltaTree()3900b57cec5SDimitry Andric DeltaTree::DeltaTree() {
3910b57cec5SDimitry Andric   Root = new DeltaTreeNode();
3920b57cec5SDimitry Andric }
3930b57cec5SDimitry Andric 
DeltaTree(const DeltaTree & RHS)3940b57cec5SDimitry Andric DeltaTree::DeltaTree(const DeltaTree &RHS) {
3950b57cec5SDimitry Andric   // Currently we only support copying when the RHS is empty.
3960b57cec5SDimitry Andric   assert(getRoot(RHS.Root)->getNumValuesUsed() == 0 &&
3970b57cec5SDimitry Andric          "Can only copy empty tree");
3980b57cec5SDimitry Andric   Root = new DeltaTreeNode();
3990b57cec5SDimitry Andric }
4000b57cec5SDimitry Andric 
~DeltaTree()4010b57cec5SDimitry Andric DeltaTree::~DeltaTree() {
4020b57cec5SDimitry Andric   getRoot(Root)->Destroy();
4030b57cec5SDimitry Andric }
4040b57cec5SDimitry Andric 
4050b57cec5SDimitry Andric /// getDeltaAt - Return the accumulated delta at the specified file offset.
4060b57cec5SDimitry Andric /// This includes all insertions or delections that occurred *before* the
4070b57cec5SDimitry Andric /// specified file index.
getDeltaAt(unsigned FileIndex) const4080b57cec5SDimitry Andric int DeltaTree::getDeltaAt(unsigned FileIndex) const {
4090b57cec5SDimitry Andric   const DeltaTreeNode *Node = getRoot(Root);
4100b57cec5SDimitry Andric 
4110b57cec5SDimitry Andric   int Result = 0;
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric   // Walk down the tree.
4140b57cec5SDimitry Andric   while (true) {
4150b57cec5SDimitry Andric     // For all nodes, include any local deltas before the specified file
4160b57cec5SDimitry Andric     // index by summing them up directly.  Keep track of how many were
4170b57cec5SDimitry Andric     // included.
4180b57cec5SDimitry Andric     unsigned NumValsGreater = 0;
4190b57cec5SDimitry Andric     for (unsigned e = Node->getNumValuesUsed(); NumValsGreater != e;
4200b57cec5SDimitry Andric          ++NumValsGreater) {
4210b57cec5SDimitry Andric       const SourceDelta &Val = Node->getValue(NumValsGreater);
4220b57cec5SDimitry Andric 
4230b57cec5SDimitry Andric       if (Val.FileLoc >= FileIndex)
4240b57cec5SDimitry Andric         break;
4250b57cec5SDimitry Andric       Result += Val.Delta;
4260b57cec5SDimitry Andric     }
4270b57cec5SDimitry Andric 
4280b57cec5SDimitry Andric     // If we have an interior node, include information about children and
4290b57cec5SDimitry Andric     // recurse.  Otherwise, if we have a leaf, we're done.
4300b57cec5SDimitry Andric     const auto *IN = dyn_cast<DeltaTreeInteriorNode>(Node);
4310b57cec5SDimitry Andric     if (!IN) return Result;
4320b57cec5SDimitry Andric 
4330b57cec5SDimitry Andric     // Include any children to the left of the values we skipped, all of
4340b57cec5SDimitry Andric     // their deltas should be included as well.
4350b57cec5SDimitry Andric     for (unsigned i = 0; i != NumValsGreater; ++i)
4360b57cec5SDimitry Andric       Result += IN->getChild(i)->getFullDelta();
4370b57cec5SDimitry Andric 
4380b57cec5SDimitry Andric     // If we found exactly the value we were looking for, break off the
4390b57cec5SDimitry Andric     // search early.  There is no need to search the RHS of the value for
4400b57cec5SDimitry Andric     // partial results.
4410b57cec5SDimitry Andric     if (NumValsGreater != Node->getNumValuesUsed() &&
4420b57cec5SDimitry Andric         Node->getValue(NumValsGreater).FileLoc == FileIndex)
4430b57cec5SDimitry Andric       return Result+IN->getChild(NumValsGreater)->getFullDelta();
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric     // Otherwise, traverse down the tree.  The selected subtree may be
4460b57cec5SDimitry Andric     // partially included in the range.
4470b57cec5SDimitry Andric     Node = IN->getChild(NumValsGreater);
4480b57cec5SDimitry Andric   }
4490b57cec5SDimitry Andric   // NOT REACHED.
4500b57cec5SDimitry Andric }
4510b57cec5SDimitry Andric 
4520b57cec5SDimitry Andric /// AddDelta - When a change is made that shifts around the text buffer,
4530b57cec5SDimitry Andric /// this method is used to record that info.  It inserts a delta of 'Delta'
4540b57cec5SDimitry Andric /// into the current DeltaTree at offset FileIndex.
AddDelta(unsigned FileIndex,int Delta)4550b57cec5SDimitry Andric void DeltaTree::AddDelta(unsigned FileIndex, int Delta) {
4560b57cec5SDimitry Andric   assert(Delta && "Adding a noop?");
4570b57cec5SDimitry Andric   DeltaTreeNode *MyRoot = getRoot(Root);
4580b57cec5SDimitry Andric 
4590b57cec5SDimitry Andric   DeltaTreeNode::InsertResult InsertRes;
4600b57cec5SDimitry Andric   if (MyRoot->DoInsertion(FileIndex, Delta, &InsertRes)) {
461*fe6060f1SDimitry Andric     Root = new DeltaTreeInteriorNode(InsertRes);
462*fe6060f1SDimitry Andric #ifdef VERIFY_TREE
463*fe6060f1SDimitry Andric     MyRoot = Root;
464*fe6060f1SDimitry Andric #endif
4650b57cec5SDimitry Andric   }
4660b57cec5SDimitry Andric 
4670b57cec5SDimitry Andric #ifdef VERIFY_TREE
4680b57cec5SDimitry Andric   VerifyTree(MyRoot);
4690b57cec5SDimitry Andric #endif
4700b57cec5SDimitry Andric }
471