From: Chris Lattner Date: Sun, 29 Mar 2009 06:06:02 +0000 (+0000) Subject: Add a simple type-safe bit-mangling pointer union class. This allows X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=2491e4657d95f7ff61fb2a741ba9996e492df515;p=oota-llvm.git Add a simple type-safe bit-mangling pointer union class. This allows you to do things like: /// PointerUnion P; /// P = (int*)0; /// printf("%d %d", P.is(), P.is()); // prints "1 0" /// X = P.get(); // ok. /// Y = P.get(); // runtime assertion failure. /// Z = P.get(); // does not compile. /// P = (float*)0; /// Y = P.get(); // ok. /// X = P.get(); // runtime assertion failure. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@67987 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/ADT/PointerUnion.h b/include/llvm/ADT/PointerUnion.h new file mode 100644 index 00000000000..8ea1315a736 --- /dev/null +++ b/include/llvm/ADT/PointerUnion.h @@ -0,0 +1,132 @@ +//===- llvm/ADT/PointerUnion.h - Discriminated Union of 2 Ptrs --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the PointerUnion class, which is a discriminated union of +// pointer types. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_POINTERUNION_H +#define LLVM_ADT_POINTERUNION_H + +#include "llvm/ADT/PointerIntPair.h" + +namespace llvm { + + /// getPointerUnionTypeNum - If the argument has type PT1* or PT2* return + /// false or true respectively. + template + static inline bool getPointerUnionTypeNum(PT1 *P) { return false; } + template + static inline bool getPointerUnionTypeNum(PT2 *P) { return true; } + // Enable, if we could use static_assert. + //template + //static inline bool getPointerUnionTypeNum(...) { abort() } + + + /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion + /// for the two template arguments. + template + class PointerUnionUIntTraits { + public: + static inline void *getAsVoidPointer(void *P) { return P; } + static inline void *getFromVoidPointer(void *P) { return P; } + enum { + PT1BitsAv = PointerLikeTypeTraits::NumLowBitsAvailable, + PT2BitsAv = PointerLikeTypeTraits::NumLowBitsAvailable, + NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv + }; + }; + + /// PointerUnion - This implements a discriminated union of two pointer types, + /// and keeps the discriminator bit-mangled into the low bits of the pointer. + /// This allows the implementation to be extremely efficient in space, but + /// permits a very natural and type-safe API. + /// + /// Common use patterns would be something like this: + /// PointerUnion P; + /// P = (int*)0; + /// printf("%d %d", P.is(), P.is()); // prints "1 0" + /// X = P.get(); // ok. + /// Y = P.get(); // runtime assertion failure. + /// Z = P.get(); // does not compile. + /// P = (float*)0; + /// Y = P.get(); // ok. + /// X = P.get(); // runtime assertion failure. + template + class PointerUnion { + public: + typedef PointerIntPair > ValTy; + private: + ValTy Val; + public: + PointerUnion() {} + + PointerUnion(PT1 V) { + Val.setPointer(V); + Val.setInt(0); + } + PointerUnion(PT2 V) { + Val.setPointer(V); + Val.setInt(1); + } + + template + int is() const { + return Val.getInt() == ::llvm::getPointerUnionTypeNum((T*)0); + } + template + T get() const { + assert(is() && "Invalid accessor called"); + return static_cast(Val.getPointer()); + } + + const PointerUnion &operator=(const PT1 &RHS) { + Val.setPointer(RHS); + Val.setInt(0); + return *this; + } + const PointerUnion &operator=(const PT2 &RHS) { + Val.setPointer(RHS); + Val.setInt(1); + return *this; + } + + void *getOpaqueValue() const { return Val.getOpaqueValue(); } + static PointerUnion getFromOpaqueValue(void *VP) { + PointerUnion V; + V.Val = ValTy::getFromOpaqueValue(VP); + return V; + } + }; + + // Teach SmallPtrSet that PointerIntPair is "basically a pointer", that has + // # low bits available = min(PT1bits,PT2bits)-1. + template + class PointerLikeTypeTraits > { + public: + static inline void * + getAsVoidPointer(const PointerUnion &P) { + return P.getOpaqueValue(); + } + static inline PointerUnion + getFromVoidPointer(void *P) { + return PointerUnion::getFromOpaqueValue(P); + } + + // The number of bits available are the min of the two pointer types. + enum { + NumLowBitsAvailable = + PointerUnion::ValTy::NumLowBitsAvailable + }; + }; +} + +#endif