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
15namespace llvm {
16
17void 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
41User *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
48unsigned 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#UserLayout
56//
57Use *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
87void 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
94const 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