//===-- 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 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(End); return ref->getInt() ? ref->getPointer() : reinterpret_cast(const_cast(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#UserLayout // 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