| //===-- Use.cpp - Implement the Use class ---------------------------------===// | |
| // | |
| // The LLVM Compiler Infrastructure | |
| // | |
| // This file is distributed under the University of Illinois Open Source | |
| // License. See LICENSE.TXT for details. | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/IR/Use.h" | |
| #include "llvm/IR/User.h" | |
| #include "llvm/IR/Value.h" | |
| #include <new> | |
| namespace llvm { | |
| void Use::swap(Use &RHS) { | |
| if (Val == RHS.Val) | |
| return; | |
| if (Val) | |
| removeFromList(); | |
| Value *OldVal = Val; | |
| if (RHS.Val) { | |
| RHS.removeFromList(); | |
| Val = RHS.Val; | |
| Val->addUse(*this); | |
| } else { | |
| Val = nullptr; | |
| } | |
| if (OldVal) { | |
| RHS.Val = OldVal; | |
| RHS.Val->addUse(RHS); | |
| } else { | |
| RHS.Val = nullptr; | |
| } | |
| } | |
| User *Use::getUser() const { | |
| const Use *End = getImpliedUser(); | |
| const UserRef *ref = reinterpret_cast<const UserRef *>(End); | |
| return ref->getInt() ? ref->getPointer() | |
| : reinterpret_cast<User *>(const_cast<Use *>(End)); | |
| } | |
| unsigned Use::getOperandNo() const { | |
| return this - getUser()->op_begin(); | |
| } | |
| // Sets up the waymarking algorithm's tags for a series of Uses. See the | |
| // algorithm details here: | |
| // | |
| // http://www.llvm.org/docs/ProgrammersManual.html#the-waymarking-algorithm | |
| // | |
| Use *Use::initTags(Use *const Start, Use *Stop) { | |
| ptrdiff_t Done = 0; | |
| while (Done < 20) { | |
| if (Start == Stop--) | |
| return Start; | |
| static const PrevPtrTag tags[20] = { | |
| fullStopTag, oneDigitTag, stopTag, oneDigitTag, oneDigitTag, | |
| stopTag, zeroDigitTag, oneDigitTag, oneDigitTag, stopTag, | |
| zeroDigitTag, oneDigitTag, zeroDigitTag, oneDigitTag, stopTag, | |
| oneDigitTag, oneDigitTag, oneDigitTag, oneDigitTag, stopTag}; | |
| new (Stop) Use(tags[Done++]); | |
| } | |
| ptrdiff_t Count = Done; | |
| while (Start != Stop) { | |
| --Stop; | |
| if (!Count) { | |
| new (Stop) Use(stopTag); | |
| ++Done; | |
| Count = Done; | |
| } else { | |
| new (Stop) Use(PrevPtrTag(Count & 1)); | |
| Count >>= 1; | |
| ++Done; | |
| } | |
| } | |
| return Start; | |
| } | |
| void Use::zap(Use *Start, const Use *Stop, bool del) { | |
| while (Start != Stop) | |
| (--Stop)->~Use(); | |
| if (del) | |
| ::operator delete(Start); | |
| } | |
| const Use *Use::getImpliedUser() const { | |
| const Use *Current = this; | |
| while (true) { | |
| unsigned Tag = (Current++)->Prev.getInt(); | |
| switch (Tag) { | |
| case zeroDigitTag: | |
| case oneDigitTag: | |
| continue; | |
| case stopTag: { | |
| ++Current; | |
| ptrdiff_t Offset = 1; | |
| while (true) { | |
| unsigned Tag = Current->Prev.getInt(); | |
| switch (Tag) { | |
| case zeroDigitTag: | |
| case oneDigitTag: | |
| ++Current; | |
| Offset = (Offset << 1) + Tag; | |
| continue; | |
| default: | |
| return Current + Offset; | |
| } | |
| } | |
| } | |
| case fullStopTag: | |
| return Current; | |
| } | |
| } | |
| } | |
| } // End llvm namespace |