<div class="doc_text">
<p>The <tt><a href="http://llvm.org/doxygen/classllvm_1_1User.html">
-User</a></tt> class provides a base for expressing the ownership of <tt>User</tt>
+User</a></tt> class provides a basis for expressing the ownership of <tt>User</tt>
towards other <tt><a href="http://llvm.org/doxygen/classllvm_1_1Value.html">
Value</a></tt>s. The <tt><a href="http://llvm.org/doxygen/classllvm_1_1Use.html">
Use</a></tt> helper class is employed to do the bookkeeping and to facilitate <i>O(1)</i>
<!-- ______________________________________________________________________ -->
<div class="doc_subsubsection">
- <a name="PATypeHolder">Interaction and relationship between <tt>User</tt> and <tt>Use</tt> objects</a>
+ <a name="Use2User">Interaction and relationship between <tt>User</tt> and <tt>Use</tt> objects</a>
</div>
<div class="doc_text">
<!-- ______________________________________________________________________ -->
<div class="doc_subsubsection">
- <a name="PATypeHolder">The waymarking algorithm</a>
+ <a name="Waymarking">The waymarking algorithm</a>
</div>
<div class="doc_text">
<!-- ______________________________________________________________________ -->
<div class="doc_subsubsection">
- <a name="PATypeHolder">Reference implementation</a>
+ <a name="ReferenceImpl">Reference implementation</a>
</div>
<div class="doc_text">
<!-- ______________________________________________________________________ -->
<div class="doc_subsubsection">
- <a name="PATypeHolder">Tagging considerations</a>
+ <a name="Tagging">Tagging considerations</a>
</div>
<p>
For layout b) instead of the <tt>User</tt> we find a pointer (<tt>User*</tt> with LSBit set).
Following this pointer brings us to the <tt>User</tt>. A portable trick ensures
that the first bytes of <tt>User</tt> (if interpreted as a pointer) never has
-the LSBit set.</p>
+the LSBit set. (Portability is relying on the fact that all known compilers place the
+<tt>vptr</tt> in the first word of the instances.)</p>
</div>
<!-- _______________________________________________________________________ -->
<div class="doc_subsubsection">
- <a name="m_Value">Important Public Methods</a>
+ <a name="m_Type">Important Public Methods</a>
</div>
<div class="doc_text">
<!-- _______________________________________________________________________ -->
<div class="doc_subsubsection">
- <a name="m_Value">Important Derived Types</a>
+ <a name="derivedtypes">Important Derived Types</a>
</div>
<div class="doc_text">
<dl>
#include "llvm/Support/Casting.h"
#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/PointerIntPair.h"
namespace llvm {
class User;
-//===----------------------------------------------------------------------===//
-// Generic Tagging Functions
-//===----------------------------------------------------------------------===//
-
-// We adhere to the following convention: The type of a tagged pointer
-// to T is T volatile*. This means that functions that superpose a tag
-// on a pointer will be supplied a T* (or T const*) and will return a
-// tagged one: T volatile*. Untagging functions do it the other way
-// 'round. While this scheme does not prevent dereferencing of tagged
-// pointers, proper type annotations do catch most inappropriate uses.
-
/// Tag - generic tag type for (at least 32 bit) pointers
enum Tag { noTag, tagOne, tagTwo, tagThree };
-/// addTag - insert tag bits into an (untagged) pointer
-template <typename T, typename TAG>
-inline volatile T *addTag(const T *P, TAG Tag) {
- return reinterpret_cast<T*>(ptrdiff_t(P) | Tag);
-}
-
-/// stripTag - remove tag bits from a pointer,
-/// making it dereferencable
-template <ptrdiff_t MASK, typename T>
-inline T *stripTag(const volatile T *P) {
- return reinterpret_cast<T*>(ptrdiff_t(P) & ~MASK);
-}
-
-/// extractTag - extract tag bits from a pointer
-template <typename TAG, TAG MASK, typename T>
-inline TAG extractTag(const volatile T *P) {
- return TAG(ptrdiff_t(P) & MASK);
-}
-
-/// transferTag - transfer tag bits from a pointer,
-/// to an untagged pointer
-template <ptrdiff_t MASK, typename T>
-inline volatile T *transferTag(const volatile T *From, const T *To) {
- return reinterpret_cast<T*>((ptrdiff_t(From) & MASK) | ptrdiff_t(To));
-}
-
//===----------------------------------------------------------------------===//
// Use Class
static Use *initTags(Use *Start, Use *Stop, ptrdiff_t Done = 0);
Value *Val;
- Use *Next, *volatile*Prev;
+ Use *Next;
+ PointerIntPair<Use**, 2, PrevPtrTag> Prev;
void setPrev(Use **NewPrev) {
- Prev = transferTag<fullStopTag>(Prev, NewPrev);
+ Prev.setPointer(NewPrev);
}
void addToList(Use **List) {
Next = *List;
*List = this;
}
void removeFromList() {
- Use **StrippedPrev = stripTag<fullStopTag>(Prev);
+ Use **StrippedPrev = Prev.getPointer();
*StrippedPrev = Next;
if (Next) Next->setPrev(StrippedPrev);
}
const Use *Current = this;
while (true) {
- unsigned Tag = extractTag<PrevPtrTag, fullStopTag>((Current++)->Prev);
+ unsigned Tag = (Current++)->Prev.getInt();
switch (Tag) {
case zeroDigitTag:
case oneDigitTag:
++Current;
ptrdiff_t Offset = 1;
while (true) {
- unsigned Tag = extractTag<PrevPtrTag, fullStopTag>(Current->Prev);
+ unsigned Tag = Current->Prev.getInt();
switch (Tag) {
case zeroDigitTag:
case oneDigitTag:
--Stop;
Stop->Val = 0;
if (!Count) {
- Stop->Prev = reinterpret_cast<Use**>(Done == 0 ? fullStopTag : stopTag);
+ Stop->Prev.setFromOpaqueValue(reinterpret_cast<Use**>(Done == 0 ? fullStopTag : stopTag));
++Done;
Count = Done;
} else {
- Stop->Prev = reinterpret_cast<Use**>(Count & 1);
+ Stop->Prev.setFromOpaqueValue(reinterpret_cast<Use**>(Count & 1));
Count >>= 1;
++Done;
}
//===----------------------------------------------------------------------===//
struct AugmentedUse : Use {
- volatile User *ref;
+ PointerIntPair<User*, 1, Tag> ref;
AugmentedUse(); // not implemented
};
User *Use::getUser() const {
const Use *End = getImpliedUser();
- volatile User *She = static_cast<const AugmentedUse*>(End - 1)->ref;
- return extractTag<Tag, tagOne>(She)
- ? llvm::stripTag<tagOne>(She)
- : reinterpret_cast<User*>(const_cast<Use*>(End));
+ PointerIntPair<User*, 1, Tag>& ref(static_cast<const AugmentedUse*>(End - 1)->ref);
+ User *She = ref.getPointer();
+ return ref.getInt()
+ ? She
+ : (User*)End;
}
//===----------------------------------------------------------------------===//
+ sizeof(AugmentedUse)
- sizeof(Use)));
Use *End = Begin + N;
- static_cast<AugmentedUse&>(End[-1]).ref = addTag(this, tagOne);
+ PointerIntPair<User*, 1, Tag>& ref(static_cast<AugmentedUse&>(End[-1]).ref);
+ ref.setPointer(const_cast<User*>(this));
+ ref.setInt(tagOne);
return Use::initTags(Begin, End);
}