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// This file implements the algorithm for finding the User of a Use.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/IR/Value.h"
15#include <new>
16
17namespace llvm {
18
19//===----------------------------------------------------------------------===//
20//                         Use swap Implementation
21//===----------------------------------------------------------------------===//
22
23void Use::swap(Use &RHS) {
24  Value *V1(Val);
25  Value *V2(RHS.Val);
26  if (V1 != V2) {
27    if (V1) {
28      removeFromList();
29    }
30
31    if (V2) {
32      RHS.removeFromList();
33      Val = V2;
34      V2->addUse(*this);
35    } else {
36      Val = 0;
37    }
38
39    if (V1) {
40      RHS.Val = V1;
41      V1->addUse(RHS);
42    } else {
43      RHS.Val = 0;
44    }
45  }
46}
47
48//===----------------------------------------------------------------------===//
49//                         Use getImpliedUser Implementation
50//===----------------------------------------------------------------------===//
51
52const Use *Use::getImpliedUser() const {
53  const Use *Current = this;
54
55  while (true) {
56    unsigned Tag = (Current++)->Prev.getInt();
57    switch (Tag) {
58      case zeroDigitTag:
59      case oneDigitTag:
60        continue;
61
62      case stopTag: {
63        ++Current;
64        ptrdiff_t Offset = 1;
65        while (true) {
66          unsigned Tag = Current->Prev.getInt();
67          switch (Tag) {
68            case zeroDigitTag:
69            case oneDigitTag:
70              ++Current;
71              Offset = (Offset << 1) + Tag;
72              continue;
73            default:
74              return Current + Offset;
75          }
76        }
77      }
78
79      case fullStopTag:
80        return Current;
81    }
82  }
83}
84
85//===----------------------------------------------------------------------===//
86//                         Use initTags Implementation
87//===----------------------------------------------------------------------===//
88
89Use *Use::initTags(Use * const Start, Use *Stop) {
90  ptrdiff_t Done = 0;
91  while (Done < 20) {
92    if (Start == Stop--)
93      return Start;
94    static const PrevPtrTag tags[20] = { fullStopTag, oneDigitTag, stopTag,
95                                         oneDigitTag, oneDigitTag, stopTag,
96                                         zeroDigitTag, oneDigitTag, oneDigitTag,
97                                         stopTag, zeroDigitTag, oneDigitTag,
98                                         zeroDigitTag, oneDigitTag, stopTag,
99                                         oneDigitTag, oneDigitTag, oneDigitTag,
100                                         oneDigitTag, stopTag
101                                       };
102    new(Stop) Use(tags[Done++]);
103  }
104
105  ptrdiff_t Count = Done;
106  while (Start != Stop) {
107    --Stop;
108    if (!Count) {
109      new(Stop) Use(stopTag);
110      ++Done;
111      Count = Done;
112    } else {
113      new(Stop) Use(PrevPtrTag(Count & 1));
114      Count >>= 1;
115      ++Done;
116    }
117  }
118
119  return Start;
120}
121
122//===----------------------------------------------------------------------===//
123//                         Use zap Implementation
124//===----------------------------------------------------------------------===//
125
126void Use::zap(Use *Start, const Use *Stop, bool del) {
127  while (Start != Stop)
128    (--Stop)->~Use();
129  if (del)
130    ::operator delete(Start);
131}
132
133//===----------------------------------------------------------------------===//
134//                         Use getUser Implementation
135//===----------------------------------------------------------------------===//
136
137User *Use::getUser() const {
138  const Use *End = getImpliedUser();
139  const UserRef *ref = reinterpret_cast<const UserRef*>(End);
140  return ref->getInt()
141    ? ref->getPointer()
142    : reinterpret_cast<User*>(const_cast<Use*>(End));
143}
144
145} // End llvm namespace
146