1
//===- llvm/ADT/PointerUnion.h - Discriminated Union of 2 Ptrs --*- C++ -*-===//
3
// The LLVM Compiler Infrastructure
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
8
//===----------------------------------------------------------------------===//
10
// This file defines the PointerUnion class, which is a discriminated union of
13
//===----------------------------------------------------------------------===//
15
#ifndef LLVM_ADT_POINTERUNION_H
16
#define LLVM_ADT_POINTERUNION_H
18
#include "llvm/ADT/PointerIntPair.h"
22
/// getPointerUnionTypeNum - If the argument has type PT1* or PT2* return
23
/// false or true respectively.
24
template <typename PT1, typename PT2>
25
static inline int getPointerUnionTypeNum(PT1 *P) { return 0; }
26
template <typename PT1, typename PT2>
27
static inline int getPointerUnionTypeNum(PT2 *P) { return 1; }
28
template <typename PT1, typename PT2>
29
static inline int getPointerUnionTypeNum(...) { return -1; }
32
/// Provide PointerLikeTypeTraits for void* that is used by PointerUnion
33
/// for the two template arguments.
34
template <typename PT1, typename PT2>
35
class PointerUnionUIntTraits {
37
static inline void *getAsVoidPointer(void *P) { return P; }
38
static inline void *getFromVoidPointer(void *P) { return P; }
40
PT1BitsAv = PointerLikeTypeTraits<PT1>::NumLowBitsAvailable,
41
PT2BitsAv = PointerLikeTypeTraits<PT2>::NumLowBitsAvailable,
42
NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv
46
/// PointerUnion - This implements a discriminated union of two pointer types,
47
/// and keeps the discriminator bit-mangled into the low bits of the pointer.
48
/// This allows the implementation to be extremely efficient in space, but
49
/// permits a very natural and type-safe API.
51
/// Common use patterns would be something like this:
52
/// PointerUnion<int*, float*> P;
54
/// printf("%d %d", P.is<int*>(), P.is<float*>()); // prints "1 0"
55
/// X = P.get<int*>(); // ok.
56
/// Y = P.get<float*>(); // runtime assertion failure.
57
/// Z = P.get<double*>(); // runtime assertion failure (regardless of tag)
59
/// Y = P.get<float*>(); // ok.
60
/// X = P.get<int*>(); // runtime assertion failure.
61
template <typename PT1, typename PT2>
64
typedef PointerIntPair<void*, 1, bool,
65
PointerUnionUIntTraits<PT1,PT2> > ValTy;
73
const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V)));
78
const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V)));
82
/// isNull - Return true if the pointer held in the union is null,
83
/// regardless of which type it is.
84
bool isNull() const { return Val.getPointer() == 0; }
85
operator bool() const { return !isNull(); }
87
/// is<T>() return true if the Union currently holds the type matching T.
90
int TyNo = ::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0);
91
assert(TyNo != -1 && "Type query could never succeed on PointerUnion!");
92
return static_cast<int>(Val.getInt()) == TyNo;
95
/// get<T>() - Return the value of the specified pointer type. If the
96
/// specified pointer type is incorrect, assert.
99
assert(is<T>() && "Invalid accessor called");
100
return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer());
103
/// dyn_cast<T>() - If the current value is of the specified pointer type,
104
/// return it, otherwise return null.
107
if (is<T>()) return get<T>();
111
/// Assignment operators - Allow assigning into this union from either
112
/// pointer type, setting the discriminator to remember what it came from.
113
const PointerUnion &operator=(const PT1 &RHS) {
115
const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS)));
119
const PointerUnion &operator=(const PT2 &RHS) {
121
const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS)));
126
void *getOpaqueValue() const { return Val.getOpaqueValue(); }
127
static PointerUnion getFromOpaqueValue(void *VP) {
129
V.Val = ValTy::getFromOpaqueValue(VP);
134
// Teach SmallPtrSet that PointerUnion is "basically a pointer", that has
135
// # low bits available = min(PT1bits,PT2bits)-1.
136
template<typename PT1, typename PT2>
137
class PointerLikeTypeTraits<PointerUnion<PT1, PT2> > {
140
getAsVoidPointer(const PointerUnion<PT1, PT2> &P) {
141
return P.getOpaqueValue();
143
static inline PointerUnion<PT1, PT2>
144
getFromVoidPointer(void *P) {
145
return PointerUnion<PT1, PT2>::getFromOpaqueValue(P);
148
// The number of bits available are the min of the two pointer types.
150
NumLowBitsAvailable =
151
PointerLikeTypeTraits<typename PointerUnion<PT1,PT2>::ValTy>
152
::NumLowBitsAvailable
157
/// PointerUnion3 - This is a pointer union of three pointer types. See
158
/// documentation for PointerUnion for usage.
159
template <typename PT1, typename PT2, typename PT3>
160
class PointerUnion3 {
162
typedef PointerUnion<PT1, PT2> InnerUnion;
163
typedef PointerUnion<InnerUnion, PT3> ValTy;
169
PointerUnion3(PT1 V) {
172
PointerUnion3(PT2 V) {
175
PointerUnion3(PT3 V) {
179
/// isNull - Return true if the pointer held in the union is null,
180
/// regardless of which type it is.
181
bool isNull() const { return Val.isNull(); }
182
operator bool() const { return !isNull(); }
184
/// is<T>() return true if the Union currently holds the type matching T.
188
if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1)
189
return Val.template is<InnerUnion>() &&
190
Val.template get<InnerUnion>().template is<T>();
191
return Val.template is<T>();
194
/// get<T>() - Return the value of the specified pointer type. If the
195
/// specified pointer type is incorrect, assert.
198
assert(is<T>() && "Invalid accessor called");
200
if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1)
201
return Val.template get<InnerUnion>().template get<T>();
203
return Val.template get<T>();
206
/// dyn_cast<T>() - If the current value is of the specified pointer type,
207
/// return it, otherwise return null.
210
if (is<T>()) return get<T>();
214
/// Assignment operators - Allow assigning into this union from either
215
/// pointer type, setting the discriminator to remember what it came from.
216
const PointerUnion3 &operator=(const PT1 &RHS) {
217
Val = InnerUnion(RHS);
220
const PointerUnion3 &operator=(const PT2 &RHS) {
221
Val = InnerUnion(RHS);
224
const PointerUnion3 &operator=(const PT3 &RHS) {
229
void *getOpaqueValue() const { return Val.getOpaqueValue(); }
230
static PointerUnion3 getFromOpaqueValue(void *VP) {
232
V.Val = ValTy::getFromOpaqueValue(VP);
237
// Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has
238
// # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
239
template<typename PT1, typename PT2, typename PT3>
240
class PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3> > {
243
getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) {
244
return P.getOpaqueValue();
246
static inline PointerUnion3<PT1, PT2, PT3>
247
getFromVoidPointer(void *P) {
248
return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P);
251
// The number of bits available are the min of the two pointer types.
253
NumLowBitsAvailable =
254
PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy>
255
::NumLowBitsAvailable
259
/// PointerUnion4 - This is a pointer union of four pointer types. See
260
/// documentation for PointerUnion for usage.
261
template <typename PT1, typename PT2, typename PT3, typename PT4>
262
class PointerUnion4 {
264
typedef PointerUnion<PT1, PT2> InnerUnion1;
265
typedef PointerUnion<PT3, PT4> InnerUnion2;
266
typedef PointerUnion<InnerUnion1, InnerUnion2> ValTy;
272
PointerUnion4(PT1 V) {
273
Val = InnerUnion1(V);
275
PointerUnion4(PT2 V) {
276
Val = InnerUnion1(V);
278
PointerUnion4(PT3 V) {
279
Val = InnerUnion2(V);
281
PointerUnion4(PT4 V) {
282
Val = InnerUnion2(V);
285
/// isNull - Return true if the pointer held in the union is null,
286
/// regardless of which type it is.
287
bool isNull() const { return Val.isNull(); }
288
operator bool() const { return !isNull(); }
290
/// is<T>() return true if the Union currently holds the type matching T.
294
if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1)
295
return Val.template is<InnerUnion1>() &&
296
Val.template get<InnerUnion1>().template is<T>();
297
return Val.template is<InnerUnion2>() &&
298
Val.template get<InnerUnion2>().template is<T>();
301
/// get<T>() - Return the value of the specified pointer type. If the
302
/// specified pointer type is incorrect, assert.
305
assert(is<T>() && "Invalid accessor called");
307
if (::llvm::getPointerUnionTypeNum<PT1, PT2>((T*)0) != -1)
308
return Val.template get<InnerUnion1>().template get<T>();
310
return Val.template get<InnerUnion2>().template get<T>();
313
/// dyn_cast<T>() - If the current value is of the specified pointer type,
314
/// return it, otherwise return null.
317
if (is<T>()) return get<T>();
321
/// Assignment operators - Allow assigning into this union from either
322
/// pointer type, setting the discriminator to remember what it came from.
323
const PointerUnion4 &operator=(const PT1 &RHS) {
324
Val = InnerUnion1(RHS);
327
const PointerUnion4 &operator=(const PT2 &RHS) {
328
Val = InnerUnion1(RHS);
331
const PointerUnion4 &operator=(const PT3 &RHS) {
332
Val = InnerUnion2(RHS);
335
const PointerUnion4 &operator=(const PT4 &RHS) {
336
Val = InnerUnion2(RHS);
340
void *getOpaqueValue() const { return Val.getOpaqueValue(); }
341
static PointerUnion4 getFromOpaqueValue(void *VP) {
343
V.Val = ValTy::getFromOpaqueValue(VP);
348
// Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has
349
// # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
350
template<typename PT1, typename PT2, typename PT3, typename PT4>
351
class PointerLikeTypeTraits<PointerUnion4<PT1, PT2, PT3, PT4> > {
354
getAsVoidPointer(const PointerUnion4<PT1, PT2, PT3, PT4> &P) {
355
return P.getOpaqueValue();
357
static inline PointerUnion4<PT1, PT2, PT3, PT4>
358
getFromVoidPointer(void *P) {
359
return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P);
362
// The number of bits available are the min of the two pointer types.
364
NumLowBitsAvailable =
365
PointerLikeTypeTraits<typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy>
366
::NumLowBitsAvailable