/3rd_party/llvm/include/llvm/ADT/PointerUnion.h

https://code.google.com/p/softart/ · C++ Header · 460 lines · 326 code · 49 blank · 85 comment · 13 complexity · fc2fa3fd44f400d393cc7a45e1be774f MD5 · raw file

  1. //===- llvm/ADT/PointerUnion.h - Discriminated Union of 2 Ptrs --*- C++ -*-===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file defines the PointerUnion class, which is a discriminated union of
  11. // pointer types.
  12. //
  13. //===----------------------------------------------------------------------===//
  14. #ifndef LLVM_ADT_POINTERUNION_H
  15. #define LLVM_ADT_POINTERUNION_H
  16. #include "llvm/Support/Compiler.h"
  17. #include "llvm/ADT/PointerIntPair.h"
  18. namespace llvm {
  19. template <typename T>
  20. struct PointerUnionTypeSelectorReturn {
  21. typedef T Return;
  22. };
  23. /// \brief Get a type based on whether two types are the same or not. For:
  24. /// @code
  25. /// typedef typename PointerUnionTypeSelector<T1, T2, EQ, NE>::Return Ret;
  26. /// @endcode
  27. /// Ret will be EQ type if T1 is same as T2 or NE type otherwise.
  28. template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
  29. struct PointerUnionTypeSelector {
  30. typedef typename PointerUnionTypeSelectorReturn<RET_NE>::Return Return;
  31. };
  32. template <typename T, typename RET_EQ, typename RET_NE>
  33. struct PointerUnionTypeSelector<T, T, RET_EQ, RET_NE> {
  34. typedef typename PointerUnionTypeSelectorReturn<RET_EQ>::Return Return;
  35. };
  36. template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
  37. struct PointerUnionTypeSelectorReturn<
  38. PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE> > {
  39. typedef typename PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE>::Return
  40. Return;
  41. };
  42. /// Provide PointerLikeTypeTraits for void* that is used by PointerUnion
  43. /// for the two template arguments.
  44. template <typename PT1, typename PT2>
  45. class PointerUnionUIntTraits {
  46. public:
  47. static inline void *getAsVoidPointer(void *P) { return P; }
  48. static inline void *getFromVoidPointer(void *P) { return P; }
  49. enum {
  50. PT1BitsAv = (int)(PointerLikeTypeTraits<PT1>::NumLowBitsAvailable),
  51. PT2BitsAv = (int)(PointerLikeTypeTraits<PT2>::NumLowBitsAvailable),
  52. NumLowBitsAvailable = PT1BitsAv < PT2BitsAv ? PT1BitsAv : PT2BitsAv
  53. };
  54. };
  55. /// PointerUnion - This implements a discriminated union of two pointer types,
  56. /// and keeps the discriminator bit-mangled into the low bits of the pointer.
  57. /// This allows the implementation to be extremely efficient in space, but
  58. /// permits a very natural and type-safe API.
  59. ///
  60. /// Common use patterns would be something like this:
  61. /// PointerUnion<int*, float*> P;
  62. /// P = (int*)0;
  63. /// printf("%d %d", P.is<int*>(), P.is<float*>()); // prints "1 0"
  64. /// X = P.get<int*>(); // ok.
  65. /// Y = P.get<float*>(); // runtime assertion failure.
  66. /// Z = P.get<double*>(); // compile time failure.
  67. /// P = (float*)0;
  68. /// Y = P.get<float*>(); // ok.
  69. /// X = P.get<int*>(); // runtime assertion failure.
  70. template <typename PT1, typename PT2>
  71. class PointerUnion {
  72. public:
  73. typedef PointerIntPair<void*, 1, bool,
  74. PointerUnionUIntTraits<PT1,PT2> > ValTy;
  75. private:
  76. ValTy Val;
  77. struct IsPT1 {
  78. static const int Num = 0;
  79. };
  80. struct IsPT2 {
  81. static const int Num = 1;
  82. };
  83. template <typename T>
  84. struct UNION_DOESNT_CONTAIN_TYPE { };
  85. public:
  86. PointerUnion() {}
  87. PointerUnion(PT1 V) : Val(
  88. const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V))) {
  89. }
  90. PointerUnion(PT2 V) : Val(
  91. const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V)), 1) {
  92. }
  93. /// isNull - Return true if the pointer held in the union is null,
  94. /// regardless of which type it is.
  95. bool isNull() const {
  96. // Convert from the void* to one of the pointer types, to make sure that
  97. // we recursively strip off low bits if we have a nested PointerUnion.
  98. return !PointerLikeTypeTraits<PT1>::getFromVoidPointer(Val.getPointer());
  99. }
  100. LLVM_EXPLICIT operator bool() const { return !isNull(); }
  101. /// is<T>() return true if the Union currently holds the type matching T.
  102. template<typename T>
  103. int is() const {
  104. typedef typename
  105. ::llvm::PointerUnionTypeSelector<PT1, T, IsPT1,
  106. ::llvm::PointerUnionTypeSelector<PT2, T, IsPT2,
  107. UNION_DOESNT_CONTAIN_TYPE<T> > >::Return Ty;
  108. int TyNo = Ty::Num;
  109. return static_cast<int>(Val.getInt()) == TyNo;
  110. }
  111. /// get<T>() - Return the value of the specified pointer type. If the
  112. /// specified pointer type is incorrect, assert.
  113. template<typename T>
  114. T get() const {
  115. assert(is<T>() && "Invalid accessor called");
  116. return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer());
  117. }
  118. /// dyn_cast<T>() - If the current value is of the specified pointer type,
  119. /// return it, otherwise return null.
  120. template<typename T>
  121. T dyn_cast() const {
  122. if (is<T>()) return get<T>();
  123. return T();
  124. }
  125. /// \brief If the union is set to the first pointer type get an address
  126. /// pointing to it.
  127. PT1 const *getAddrOfPtr1() const {
  128. return const_cast<PointerUnion *>(this)->getAddrOfPtr1();
  129. }
  130. /// \brief If the union is set to the first pointer type get an address
  131. /// pointing to it.
  132. PT1 *getAddrOfPtr1() {
  133. assert(is<PT1>() && "Val is not the first pointer");
  134. assert(get<PT1>() == Val.getPointer() &&
  135. "Can't get the address because PointerLikeTypeTraits changes the ptr");
  136. return (PT1 *)Val.getAddrOfPointer();
  137. }
  138. /// Assignment operators - Allow assigning into this union from either
  139. /// pointer type, setting the discriminator to remember what it came from.
  140. const PointerUnion &operator=(const PT1 &RHS) {
  141. Val.initWithPointer(
  142. const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS)));
  143. return *this;
  144. }
  145. const PointerUnion &operator=(const PT2 &RHS) {
  146. Val.setPointerAndInt(
  147. const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS)),
  148. 1);
  149. return *this;
  150. }
  151. void *getOpaqueValue() const { return Val.getOpaqueValue(); }
  152. static inline PointerUnion getFromOpaqueValue(void *VP) {
  153. PointerUnion V;
  154. V.Val = ValTy::getFromOpaqueValue(VP);
  155. return V;
  156. }
  157. };
  158. template<typename PT1, typename PT2>
  159. static bool operator==(PointerUnion<PT1, PT2> lhs,
  160. PointerUnion<PT1, PT2> rhs) {
  161. return lhs.getOpaqueValue() == rhs.getOpaqueValue();
  162. }
  163. template<typename PT1, typename PT2>
  164. static bool operator!=(PointerUnion<PT1, PT2> lhs,
  165. PointerUnion<PT1, PT2> rhs) {
  166. return lhs.getOpaqueValue() != rhs.getOpaqueValue();
  167. }
  168. // Teach SmallPtrSet that PointerUnion is "basically a pointer", that has
  169. // # low bits available = min(PT1bits,PT2bits)-1.
  170. template<typename PT1, typename PT2>
  171. class PointerLikeTypeTraits<PointerUnion<PT1, PT2> > {
  172. public:
  173. static inline void *
  174. getAsVoidPointer(const PointerUnion<PT1, PT2> &P) {
  175. return P.getOpaqueValue();
  176. }
  177. static inline PointerUnion<PT1, PT2>
  178. getFromVoidPointer(void *P) {
  179. return PointerUnion<PT1, PT2>::getFromOpaqueValue(P);
  180. }
  181. // The number of bits available are the min of the two pointer types.
  182. enum {
  183. NumLowBitsAvailable =
  184. PointerLikeTypeTraits<typename PointerUnion<PT1,PT2>::ValTy>
  185. ::NumLowBitsAvailable
  186. };
  187. };
  188. /// PointerUnion3 - This is a pointer union of three pointer types. See
  189. /// documentation for PointerUnion for usage.
  190. template <typename PT1, typename PT2, typename PT3>
  191. class PointerUnion3 {
  192. public:
  193. typedef PointerUnion<PT1, PT2> InnerUnion;
  194. typedef PointerUnion<InnerUnion, PT3> ValTy;
  195. private:
  196. ValTy Val;
  197. struct IsInnerUnion {
  198. ValTy Val;
  199. IsInnerUnion(ValTy val) : Val(val) { }
  200. template<typename T>
  201. int is() const {
  202. return Val.template is<InnerUnion>() &&
  203. Val.template get<InnerUnion>().template is<T>();
  204. }
  205. template<typename T>
  206. T get() const {
  207. return Val.template get<InnerUnion>().template get<T>();
  208. }
  209. };
  210. struct IsPT3 {
  211. ValTy Val;
  212. IsPT3(ValTy val) : Val(val) { }
  213. template<typename T>
  214. int is() const {
  215. return Val.template is<T>();
  216. }
  217. template<typename T>
  218. T get() const {
  219. return Val.template get<T>();
  220. }
  221. };
  222. public:
  223. PointerUnion3() {}
  224. PointerUnion3(PT1 V) {
  225. Val = InnerUnion(V);
  226. }
  227. PointerUnion3(PT2 V) {
  228. Val = InnerUnion(V);
  229. }
  230. PointerUnion3(PT3 V) {
  231. Val = V;
  232. }
  233. /// isNull - Return true if the pointer held in the union is null,
  234. /// regardless of which type it is.
  235. bool isNull() const { return Val.isNull(); }
  236. LLVM_EXPLICIT operator bool() const { return !isNull(); }
  237. /// is<T>() return true if the Union currently holds the type matching T.
  238. template<typename T>
  239. int is() const {
  240. // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3.
  241. typedef typename
  242. ::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion,
  243. ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 >
  244. >::Return Ty;
  245. return Ty(Val).template is<T>();
  246. }
  247. /// get<T>() - Return the value of the specified pointer type. If the
  248. /// specified pointer type is incorrect, assert.
  249. template<typename T>
  250. T get() const {
  251. assert(is<T>() && "Invalid accessor called");
  252. // If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3.
  253. typedef typename
  254. ::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion,
  255. ::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 >
  256. >::Return Ty;
  257. return Ty(Val).template get<T>();
  258. }
  259. /// dyn_cast<T>() - If the current value is of the specified pointer type,
  260. /// return it, otherwise return null.
  261. template<typename T>
  262. T dyn_cast() const {
  263. if (is<T>()) return get<T>();
  264. return T();
  265. }
  266. /// Assignment operators - Allow assigning into this union from either
  267. /// pointer type, setting the discriminator to remember what it came from.
  268. const PointerUnion3 &operator=(const PT1 &RHS) {
  269. Val = InnerUnion(RHS);
  270. return *this;
  271. }
  272. const PointerUnion3 &operator=(const PT2 &RHS) {
  273. Val = InnerUnion(RHS);
  274. return *this;
  275. }
  276. const PointerUnion3 &operator=(const PT3 &RHS) {
  277. Val = RHS;
  278. return *this;
  279. }
  280. void *getOpaqueValue() const { return Val.getOpaqueValue(); }
  281. static inline PointerUnion3 getFromOpaqueValue(void *VP) {
  282. PointerUnion3 V;
  283. V.Val = ValTy::getFromOpaqueValue(VP);
  284. return V;
  285. }
  286. };
  287. // Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has
  288. // # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
  289. template<typename PT1, typename PT2, typename PT3>
  290. class PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3> > {
  291. public:
  292. static inline void *
  293. getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) {
  294. return P.getOpaqueValue();
  295. }
  296. static inline PointerUnion3<PT1, PT2, PT3>
  297. getFromVoidPointer(void *P) {
  298. return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P);
  299. }
  300. // The number of bits available are the min of the two pointer types.
  301. enum {
  302. NumLowBitsAvailable =
  303. PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy>
  304. ::NumLowBitsAvailable
  305. };
  306. };
  307. /// PointerUnion4 - This is a pointer union of four pointer types. See
  308. /// documentation for PointerUnion for usage.
  309. template <typename PT1, typename PT2, typename PT3, typename PT4>
  310. class PointerUnion4 {
  311. public:
  312. typedef PointerUnion<PT1, PT2> InnerUnion1;
  313. typedef PointerUnion<PT3, PT4> InnerUnion2;
  314. typedef PointerUnion<InnerUnion1, InnerUnion2> ValTy;
  315. private:
  316. ValTy Val;
  317. public:
  318. PointerUnion4() {}
  319. PointerUnion4(PT1 V) {
  320. Val = InnerUnion1(V);
  321. }
  322. PointerUnion4(PT2 V) {
  323. Val = InnerUnion1(V);
  324. }
  325. PointerUnion4(PT3 V) {
  326. Val = InnerUnion2(V);
  327. }
  328. PointerUnion4(PT4 V) {
  329. Val = InnerUnion2(V);
  330. }
  331. /// isNull - Return true if the pointer held in the union is null,
  332. /// regardless of which type it is.
  333. bool isNull() const { return Val.isNull(); }
  334. LLVM_EXPLICIT operator bool() const { return !isNull(); }
  335. /// is<T>() return true if the Union currently holds the type matching T.
  336. template<typename T>
  337. int is() const {
  338. // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2.
  339. typedef typename
  340. ::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1,
  341. ::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 >
  342. >::Return Ty;
  343. return Val.template is<Ty>() &&
  344. Val.template get<Ty>().template is<T>();
  345. }
  346. /// get<T>() - Return the value of the specified pointer type. If the
  347. /// specified pointer type is incorrect, assert.
  348. template<typename T>
  349. T get() const {
  350. assert(is<T>() && "Invalid accessor called");
  351. // If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2.
  352. typedef typename
  353. ::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1,
  354. ::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 >
  355. >::Return Ty;
  356. return Val.template get<Ty>().template get<T>();
  357. }
  358. /// dyn_cast<T>() - If the current value is of the specified pointer type,
  359. /// return it, otherwise return null.
  360. template<typename T>
  361. T dyn_cast() const {
  362. if (is<T>()) return get<T>();
  363. return T();
  364. }
  365. /// Assignment operators - Allow assigning into this union from either
  366. /// pointer type, setting the discriminator to remember what it came from.
  367. const PointerUnion4 &operator=(const PT1 &RHS) {
  368. Val = InnerUnion1(RHS);
  369. return *this;
  370. }
  371. const PointerUnion4 &operator=(const PT2 &RHS) {
  372. Val = InnerUnion1(RHS);
  373. return *this;
  374. }
  375. const PointerUnion4 &operator=(const PT3 &RHS) {
  376. Val = InnerUnion2(RHS);
  377. return *this;
  378. }
  379. const PointerUnion4 &operator=(const PT4 &RHS) {
  380. Val = InnerUnion2(RHS);
  381. return *this;
  382. }
  383. void *getOpaqueValue() const { return Val.getOpaqueValue(); }
  384. static inline PointerUnion4 getFromOpaqueValue(void *VP) {
  385. PointerUnion4 V;
  386. V.Val = ValTy::getFromOpaqueValue(VP);
  387. return V;
  388. }
  389. };
  390. // Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has
  391. // # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
  392. template<typename PT1, typename PT2, typename PT3, typename PT4>
  393. class PointerLikeTypeTraits<PointerUnion4<PT1, PT2, PT3, PT4> > {
  394. public:
  395. static inline void *
  396. getAsVoidPointer(const PointerUnion4<PT1, PT2, PT3, PT4> &P) {
  397. return P.getOpaqueValue();
  398. }
  399. static inline PointerUnion4<PT1, PT2, PT3, PT4>
  400. getFromVoidPointer(void *P) {
  401. return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P);
  402. }
  403. // The number of bits available are the min of the two pointer types.
  404. enum {
  405. NumLowBitsAvailable =
  406. PointerLikeTypeTraits<typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy>
  407. ::NumLowBitsAvailable
  408. };
  409. };
  410. }
  411. #endif