InterferenceCache.h revision 6ef7da0197735a16aa534e9e2c80709d3d6e8c56
15907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen//===-- InterferenceCache.h - Caching per-block interference ---*- C++ -*--===// 25907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen// 35907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen// The LLVM Compiler Infrastructure 45907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen// 55907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen// This file is distributed under the University of Illinois Open Source 65907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen// License. See LICENSE.TXT for details. 75907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen// 85907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen//===----------------------------------------------------------------------===// 95907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen// 105907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen// InterferenceCache remembers per-block interference in LiveIntervalUnions. 115907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen// 125907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen//===----------------------------------------------------------------------===// 135907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 145907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen#ifndef LLVM_CODEGEN_INTERFERENCECACHE 155907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen#define LLVM_CODEGEN_INTERFERENCECACHE 165907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 175907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen#include "LiveIntervalUnion.h" 185907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 195907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesennamespace llvm { 205907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 216ef7da0197735a16aa534e9e2c80709d3d6e8c56Jakob Stoklund Olesenclass LiveIntervals; 226ef7da0197735a16aa534e9e2c80709d3d6e8c56Jakob Stoklund Olesen 235907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesenclass InterferenceCache { 245907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen const TargetRegisterInfo *TRI; 255907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen LiveIntervalUnion *LIUArray; 265907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen MachineFunction *MF; 275907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 285907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen /// BlockInterference - information about the interference in a single basic 295907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen /// block. 305907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen struct BlockInterference { 315907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen BlockInterference() : Tag(0) {} 325907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen unsigned Tag; 335907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen SlotIndex First; 345907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen SlotIndex Last; 355907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen }; 365907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 375907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen /// Entry - A cache entry containing interference information for all aliases 385907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen /// of PhysReg in all basic blocks. 395907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen class Entry { 405907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen /// PhysReg - The register currently represented. 415907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen unsigned PhysReg; 425907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 435907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen /// Tag - Cache tag is changed when any of the underlying LiveIntervalUnions 445907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen /// change. 455907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen unsigned Tag; 465907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 47f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen /// RefCount - The total number of Cursor instances referring to this Entry. 48f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen unsigned RefCount; 49f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen 509d29cbad32814f31c91cd2464a3c74df412b0aacJakob Stoklund Olesen /// MF - The current function. 519d29cbad32814f31c91cd2464a3c74df412b0aacJakob Stoklund Olesen MachineFunction *MF; 529d29cbad32814f31c91cd2464a3c74df412b0aacJakob Stoklund Olesen 535907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen /// Indexes - Mapping block numbers to SlotIndex ranges. 545907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen SlotIndexes *Indexes; 555907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 566ef7da0197735a16aa534e9e2c80709d3d6e8c56Jakob Stoklund Olesen /// LIS - Used for accessing register mask interference maps. 576ef7da0197735a16aa534e9e2c80709d3d6e8c56Jakob Stoklund Olesen LiveIntervals *LIS; 586ef7da0197735a16aa534e9e2c80709d3d6e8c56Jakob Stoklund Olesen 595907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen /// PrevPos - The previous position the iterators were moved to. 605907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen SlotIndex PrevPos; 615907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 625907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen /// AliasTags - A LiveIntervalUnion pointer and tag for each alias of 635907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen /// PhysReg. 645907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen SmallVector<std::pair<LiveIntervalUnion*, unsigned>, 8> Aliases; 655907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 665907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen typedef LiveIntervalUnion::SegmentIter Iter; 675907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 685907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen /// Iters - an iterator for each alias 695907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen SmallVector<Iter, 8> Iters; 705907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 715907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen /// Blocks - Interference for each block in the function. 725907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen SmallVector<BlockInterference, 8> Blocks; 735907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 745907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen /// update - Recompute Blocks[MBBNum] 755907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen void update(unsigned MBBNum); 765907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 775907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen public: 786ef7da0197735a16aa534e9e2c80709d3d6e8c56Jakob Stoklund Olesen Entry() : PhysReg(0), Tag(0), RefCount(0), Indexes(0), LIS(0) {} 795907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 806ef7da0197735a16aa534e9e2c80709d3d6e8c56Jakob Stoklund Olesen void clear(MachineFunction *mf, SlotIndexes *indexes, LiveIntervals *lis) { 81f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen assert(!hasRefs() && "Cannot clear cache entry with references"); 825907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen PhysReg = 0; 839d29cbad32814f31c91cd2464a3c74df412b0aacJakob Stoklund Olesen MF = mf; 845907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen Indexes = indexes; 856ef7da0197735a16aa534e9e2c80709d3d6e8c56Jakob Stoklund Olesen LIS = lis; 865907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen } 875907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 885907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen unsigned getPhysReg() const { return PhysReg; } 895907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 90f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen void addRef(int Delta) { RefCount += Delta; } 91f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen 92f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen bool hasRefs() const { return RefCount > 0; } 93f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen 945907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen void revalidate(); 955907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 965907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen /// valid - Return true if this is a valid entry for physReg. 975907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen bool valid(LiveIntervalUnion *LIUArray, const TargetRegisterInfo *TRI); 985907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 995907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen /// reset - Initialize entry to represent physReg's aliases. 1005907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen void reset(unsigned physReg, 1015907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen LiveIntervalUnion *LIUArray, 1025907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen const TargetRegisterInfo *TRI, 1035907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen const MachineFunction *MF); 1045907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 1055907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen /// get - Return an up to date BlockInterference. 1065907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen BlockInterference *get(unsigned MBBNum) { 1075907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen if (Blocks[MBBNum].Tag != Tag) 1085907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen update(MBBNum); 1095907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen return &Blocks[MBBNum]; 1105907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen } 1115907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen }; 1125907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 1135907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen // We don't keep a cache entry for every physical register, that would use too 1145907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen // much memory. Instead, a fixed number of cache entries are used in a round- 1155907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen // robin manner. 1165907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen enum { CacheEntries = 32 }; 1175907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 1185907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen // Point to an entry for each physreg. The entry pointed to may not be up to 1195907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen // date, and it may have been reused for a different physreg. 1205907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen SmallVector<unsigned char, 2> PhysRegEntries; 1215907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 1225907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen // Next round-robin entry to be picked. 1235907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen unsigned RoundRobin; 1245907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 1255907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen // The actual cache entries. 1265907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen Entry Entries[CacheEntries]; 1275907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 1285907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen // get - Get a valid entry for PhysReg. 1295907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen Entry *get(unsigned PhysReg); 1305907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 1315907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesenpublic: 1323bf7a1cc3c090e766b8912c6a14c3e2ec5dde7f8Jakob Stoklund Olesen InterferenceCache() : TRI(0), LIUArray(0), MF(0), RoundRobin(0) {} 1335907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 1345907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen /// init - Prepare cache for a new function. 1356ef7da0197735a16aa534e9e2c80709d3d6e8c56Jakob Stoklund Olesen void init(MachineFunction*, LiveIntervalUnion*, SlotIndexes*, LiveIntervals*, 1365907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen const TargetRegisterInfo *); 1375907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 138f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen /// getMaxCursors - Return the maximum number of concurrent cursors that can 139f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen /// be supported. 140f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen unsigned getMaxCursors() const { return CacheEntries; } 141f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen 1425907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen /// Cursor - The primary query interface for the block interference cache. 1435907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen class Cursor { 1445907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen Entry *CacheEntry; 1455907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen BlockInterference *Current; 146c7931fd725b390142f9112952b1426560000e6b4Jakob Stoklund Olesen static BlockInterference NoInterference; 147f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen 148f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen void setEntry(Entry *E) { 149f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen Current = 0; 150f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen // Update reference counts. Nothing happens when RefCount reaches 0, so 151f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen // we don't have to check for E == CacheEntry etc. 152f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen if (CacheEntry) 153f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen CacheEntry->addRef(-1); 154f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen CacheEntry = E; 155f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen if (CacheEntry) 156f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen CacheEntry->addRef(+1); 157f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen } 158f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen 1595907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen public: 160c66a37df73f70ec3dbed06277763624f33ee3512Jakob Stoklund Olesen /// Cursor - Create a dangling cursor. 161c66a37df73f70ec3dbed06277763624f33ee3512Jakob Stoklund Olesen Cursor() : CacheEntry(0), Current(0) {} 162f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen ~Cursor() { setEntry(0); } 163f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen 164f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen Cursor(const Cursor &O) : CacheEntry(0), Current(0) { 165f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen setEntry(O.CacheEntry); 166f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen } 167f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen 168f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen Cursor &operator=(const Cursor &O) { 169f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen setEntry(O.CacheEntry); 170f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen return *this; 171f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen } 172c66a37df73f70ec3dbed06277763624f33ee3512Jakob Stoklund Olesen 173c66a37df73f70ec3dbed06277763624f33ee3512Jakob Stoklund Olesen /// setPhysReg - Point this cursor to PhysReg's interference. 174c66a37df73f70ec3dbed06277763624f33ee3512Jakob Stoklund Olesen void setPhysReg(InterferenceCache &Cache, unsigned PhysReg) { 175f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen // Release reference before getting a new one. That guarantees we can 176f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen // actually have CacheEntries live cursors. 177f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen setEntry(0); 178f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen if (PhysReg) 179f1c709837bd11c5383fce3b8a026a7c8eaabba86Jakob Stoklund Olesen setEntry(Cache.get(PhysReg)); 180c66a37df73f70ec3dbed06277763624f33ee3512Jakob Stoklund Olesen } 1815907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 1825907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen /// moveTo - Move cursor to basic block MBBNum. 1835907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen void moveToBlock(unsigned MBBNum) { 184c7931fd725b390142f9112952b1426560000e6b4Jakob Stoklund Olesen Current = CacheEntry ? CacheEntry->get(MBBNum) : &NoInterference; 1855907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen } 1865907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 1875907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen /// hasInterference - Return true if the current block has any interference. 1885907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen bool hasInterference() { 1895907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen return Current->First.isValid(); 1905907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen } 1915907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 1925907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen /// first - Return the starting index of the first interfering range in the 1935907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen /// current block. 1945907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen SlotIndex first() { 1955907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen return Current->First; 1965907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen } 1975907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 1985907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen /// last - Return the ending index of the last interfering range in the 1995907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen /// current block. 2005907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen SlotIndex last() { 2015907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen return Current->Last; 2025907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen } 2035907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen }; 2045907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 2055907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen friend class Cursor; 2065907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen}; 2075907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 2085907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen} // namespace llvm 2095907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen 2105907d863659eb972ebb2afe07bc863a4c616f0efJakob Stoklund Olesen#endif 211