Home | History | Annotate | Download | only in IR
      1 //===-- Use.cpp - Implement the Use class ---------------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "llvm/IR/Use.h"
     11 #include "llvm/IR/User.h"
     12 #include "llvm/IR/Value.h"
     13 #include <new>
     14 
     15 namespace llvm {
     16 
     17 void Use::swap(Use &RHS) {
     18   if (Val == RHS.Val)
     19     return;
     20 
     21   if (Val)
     22     removeFromList();
     23 
     24   Value *OldVal = Val;
     25   if (RHS.Val) {
     26     RHS.removeFromList();
     27     Val = RHS.Val;
     28     Val->addUse(*this);
     29   } else {
     30     Val = nullptr;
     31   }
     32 
     33   if (OldVal) {
     34     RHS.Val = OldVal;
     35     RHS.Val->addUse(RHS);
     36   } else {
     37     RHS.Val = nullptr;
     38   }
     39 }
     40 
     41 User *Use::getUser() const {
     42   const Use *End = getImpliedUser();
     43   const UserRef *ref = reinterpret_cast<const UserRef *>(End);
     44   return ref->getInt() ? ref->getPointer()
     45                        : reinterpret_cast<User *>(const_cast<Use *>(End));
     46 }
     47 
     48 unsigned Use::getOperandNo() const {
     49   return this - getUser()->op_begin();
     50 }
     51 
     52 // Sets up the waymarking algorithm's tags for a series of Uses. See the
     53 // algorithm details here:
     54 //
     55 //   http://www.llvm.org/docs/ProgrammersManual.html#the-waymarking-algorithm
     56 //
     57 Use *Use::initTags(Use *const Start, Use *Stop) {
     58   ptrdiff_t Done = 0;
     59   while (Done < 20) {
     60     if (Start == Stop--)
     61       return Start;
     62     static const PrevPtrTag tags[20] = {
     63         fullStopTag,  oneDigitTag,  stopTag,      oneDigitTag, oneDigitTag,
     64         stopTag,      zeroDigitTag, oneDigitTag,  oneDigitTag, stopTag,
     65         zeroDigitTag, oneDigitTag,  zeroDigitTag, oneDigitTag, stopTag,
     66         oneDigitTag,  oneDigitTag,  oneDigitTag,  oneDigitTag, stopTag};
     67     new (Stop) Use(tags[Done++]);
     68   }
     69 
     70   ptrdiff_t Count = Done;
     71   while (Start != Stop) {
     72     --Stop;
     73     if (!Count) {
     74       new (Stop) Use(stopTag);
     75       ++Done;
     76       Count = Done;
     77     } else {
     78       new (Stop) Use(PrevPtrTag(Count & 1));
     79       Count >>= 1;
     80       ++Done;
     81     }
     82   }
     83 
     84   return Start;
     85 }
     86 
     87 void Use::zap(Use *Start, const Use *Stop, bool del) {
     88   while (Start != Stop)
     89     (--Stop)->~Use();
     90   if (del)
     91     ::operator delete(Start);
     92 }
     93 
     94 const Use *Use::getImpliedUser() const {
     95   const Use *Current = this;
     96 
     97   while (true) {
     98     unsigned Tag = (Current++)->Prev.getInt();
     99     switch (Tag) {
    100     case zeroDigitTag:
    101     case oneDigitTag:
    102       continue;
    103 
    104     case stopTag: {
    105       ++Current;
    106       ptrdiff_t Offset = 1;
    107       while (true) {
    108         unsigned Tag = Current->Prev.getInt();
    109         switch (Tag) {
    110         case zeroDigitTag:
    111         case oneDigitTag:
    112           ++Current;
    113           Offset = (Offset << 1) + Tag;
    114           continue;
    115         default:
    116           return Current + Offset;
    117         }
    118       }
    119     }
    120 
    121     case fullStopTag:
    122       return Current;
    123     }
    124   }
    125 }
    126 
    127 } // End llvm namespace
    128