1249259Sdim//===-- Use.cpp - Implement the Use class ---------------------------------===//
2249259Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6249259Sdim//
7249259Sdim//===----------------------------------------------------------------------===//
8249259Sdim
9276479Sdim#include "llvm/IR/Use.h"
10276479Sdim#include "llvm/IR/User.h"
11249259Sdim#include "llvm/IR/Value.h"
12249259Sdim#include <new>
13249259Sdim
14249259Sdimnamespace llvm {
15249259Sdim
16249259Sdimvoid Use::swap(Use &RHS) {
17276479Sdim  if (Val == RHS.Val)
18276479Sdim    return;
19249259Sdim
20276479Sdim  if (Val)
21276479Sdim    removeFromList();
22249259Sdim
23276479Sdim  Value *OldVal = Val;
24276479Sdim  if (RHS.Val) {
25276479Sdim    RHS.removeFromList();
26276479Sdim    Val = RHS.Val;
27276479Sdim    Val->addUse(*this);
28276479Sdim  } else {
29276479Sdim    Val = nullptr;
30249259Sdim  }
31276479Sdim
32276479Sdim  if (OldVal) {
33276479Sdim    RHS.Val = OldVal;
34276479Sdim    RHS.Val->addUse(RHS);
35276479Sdim  } else {
36276479Sdim    RHS.Val = nullptr;
37276479Sdim  }
38249259Sdim}
39249259Sdim
40276479SdimUser *Use::getUser() const {
41276479Sdim  const Use *End = getImpliedUser();
42276479Sdim  const UserRef *ref = reinterpret_cast<const UserRef *>(End);
43276479Sdim  return ref->getInt() ? ref->getPointer()
44276479Sdim                       : reinterpret_cast<User *>(const_cast<Use *>(End));
45276479Sdim}
46249259Sdim
47276479Sdimunsigned Use::getOperandNo() const {
48276479Sdim  return this - getUser()->op_begin();
49249259Sdim}
50249259Sdim
51276479Sdim// Sets up the waymarking algorithm's tags for a series of Uses. See the
52276479Sdim// algorithm details here:
53276479Sdim//
54280031Sdim//   http://www.llvm.org/docs/ProgrammersManual.html#the-waymarking-algorithm
55276479Sdim//
56276479SdimUse *Use::initTags(Use *const Start, Use *Stop) {
57249259Sdim  ptrdiff_t Done = 0;
58249259Sdim  while (Done < 20) {
59249259Sdim    if (Start == Stop--)
60249259Sdim      return Start;
61276479Sdim    static const PrevPtrTag tags[20] = {
62276479Sdim        fullStopTag,  oneDigitTag,  stopTag,      oneDigitTag, oneDigitTag,
63276479Sdim        stopTag,      zeroDigitTag, oneDigitTag,  oneDigitTag, stopTag,
64276479Sdim        zeroDigitTag, oneDigitTag,  zeroDigitTag, oneDigitTag, stopTag,
65276479Sdim        oneDigitTag,  oneDigitTag,  oneDigitTag,  oneDigitTag, stopTag};
66276479Sdim    new (Stop) Use(tags[Done++]);
67249259Sdim  }
68249259Sdim
69249259Sdim  ptrdiff_t Count = Done;
70249259Sdim  while (Start != Stop) {
71249259Sdim    --Stop;
72249259Sdim    if (!Count) {
73276479Sdim      new (Stop) Use(stopTag);
74249259Sdim      ++Done;
75249259Sdim      Count = Done;
76249259Sdim    } else {
77276479Sdim      new (Stop) Use(PrevPtrTag(Count & 1));
78249259Sdim      Count >>= 1;
79249259Sdim      ++Done;
80249259Sdim    }
81249259Sdim  }
82249259Sdim
83249259Sdim  return Start;
84249259Sdim}
85249259Sdim
86249259Sdimvoid Use::zap(Use *Start, const Use *Stop, bool del) {
87249259Sdim  while (Start != Stop)
88249259Sdim    (--Stop)->~Use();
89249259Sdim  if (del)
90249259Sdim    ::operator delete(Start);
91249259Sdim}
92249259Sdim
93276479Sdimconst Use *Use::getImpliedUser() const {
94276479Sdim  const Use *Current = this;
95249259Sdim
96276479Sdim  while (true) {
97276479Sdim    unsigned Tag = (Current++)->Prev.getInt();
98276479Sdim    switch (Tag) {
99276479Sdim    case zeroDigitTag:
100276479Sdim    case oneDigitTag:
101276479Sdim      continue;
102276479Sdim
103276479Sdim    case stopTag: {
104276479Sdim      ++Current;
105276479Sdim      ptrdiff_t Offset = 1;
106276479Sdim      while (true) {
107276479Sdim        unsigned Tag = Current->Prev.getInt();
108276479Sdim        switch (Tag) {
109276479Sdim        case zeroDigitTag:
110276479Sdim        case oneDigitTag:
111276479Sdim          ++Current;
112276479Sdim          Offset = (Offset << 1) + Tag;
113276479Sdim          continue;
114276479Sdim        default:
115276479Sdim          return Current + Offset;
116276479Sdim        }
117276479Sdim      }
118276479Sdim    }
119276479Sdim
120276479Sdim    case fullStopTag:
121276479Sdim      return Current;
122276479Sdim    }
123276479Sdim  }
124249259Sdim}
125249259Sdim
126249259Sdim} // End llvm namespace
127