mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-12-28 04:33:05 +00:00
974a445bd9
subsequent changes are easier to review. About to fix some layering issues, and wanted to separate out the necessary churn. Also comment and sink the include of "Windows.h" in three .inc files to match the usage in Memory.inc. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@198685 91177308-0d34-0410-b5e6-96231b3b80d8
461 lines
15 KiB
C++
461 lines
15 KiB
C++
//===- 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"
|
|
#include "llvm/Support/Compiler.h"
|
|
|
|
namespace llvm {
|
|
|
|
template <typename T>
|
|
struct PointerUnionTypeSelectorReturn {
|
|
typedef T Return;
|
|
};
|
|
|
|
/// \brief Get a type based on whether two types are the same or not. For:
|
|
/// @code
|
|
/// typedef typename PointerUnionTypeSelector<T1, T2, EQ, NE>::Return Ret;
|
|
/// @endcode
|
|
/// Ret will be EQ type if T1 is same as T2 or NE type otherwise.
|
|
template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
|
|
struct PointerUnionTypeSelector {
|
|
typedef typename PointerUnionTypeSelectorReturn<RET_NE>::Return Return;
|
|
};
|
|
|
|
template <typename T, typename RET_EQ, typename RET_NE>
|
|
struct PointerUnionTypeSelector<T, T, RET_EQ, RET_NE> {
|
|
typedef typename PointerUnionTypeSelectorReturn<RET_EQ>::Return Return;
|
|
};
|
|
|
|
template <typename T1, typename T2, typename RET_EQ, typename RET_NE>
|
|
struct PointerUnionTypeSelectorReturn<
|
|
PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE> > {
|
|
typedef typename PointerUnionTypeSelector<T1, T2, RET_EQ, RET_NE>::Return
|
|
Return;
|
|
};
|
|
|
|
/// Provide PointerLikeTypeTraits for void* that is used by PointerUnion
|
|
/// for the two template arguments.
|
|
template <typename PT1, typename PT2>
|
|
class PointerUnionUIntTraits {
|
|
public:
|
|
static inline void *getAsVoidPointer(void *P) { return P; }
|
|
static inline void *getFromVoidPointer(void *P) { return P; }
|
|
enum {
|
|
PT1BitsAv = (int)(PointerLikeTypeTraits<PT1>::NumLowBitsAvailable),
|
|
PT2BitsAv = (int)(PointerLikeTypeTraits<PT2>::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<int*, float*> P;
|
|
/// P = (int*)0;
|
|
/// printf("%d %d", P.is<int*>(), P.is<float*>()); // prints "1 0"
|
|
/// X = P.get<int*>(); // ok.
|
|
/// Y = P.get<float*>(); // runtime assertion failure.
|
|
/// Z = P.get<double*>(); // compile time failure.
|
|
/// P = (float*)0;
|
|
/// Y = P.get<float*>(); // ok.
|
|
/// X = P.get<int*>(); // runtime assertion failure.
|
|
template <typename PT1, typename PT2>
|
|
class PointerUnion {
|
|
public:
|
|
typedef PointerIntPair<void*, 1, bool,
|
|
PointerUnionUIntTraits<PT1,PT2> > ValTy;
|
|
private:
|
|
ValTy Val;
|
|
|
|
struct IsPT1 {
|
|
static const int Num = 0;
|
|
};
|
|
struct IsPT2 {
|
|
static const int Num = 1;
|
|
};
|
|
template <typename T>
|
|
struct UNION_DOESNT_CONTAIN_TYPE { };
|
|
|
|
public:
|
|
PointerUnion() {}
|
|
|
|
PointerUnion(PT1 V) : Val(
|
|
const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(V))) {
|
|
}
|
|
PointerUnion(PT2 V) : Val(
|
|
const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(V)), 1) {
|
|
}
|
|
|
|
/// isNull - Return true if the pointer held in the union is null,
|
|
/// regardless of which type it is.
|
|
bool isNull() const {
|
|
// Convert from the void* to one of the pointer types, to make sure that
|
|
// we recursively strip off low bits if we have a nested PointerUnion.
|
|
return !PointerLikeTypeTraits<PT1>::getFromVoidPointer(Val.getPointer());
|
|
}
|
|
LLVM_EXPLICIT operator bool() const { return !isNull(); }
|
|
|
|
/// is<T>() return true if the Union currently holds the type matching T.
|
|
template<typename T>
|
|
int is() const {
|
|
typedef typename
|
|
::llvm::PointerUnionTypeSelector<PT1, T, IsPT1,
|
|
::llvm::PointerUnionTypeSelector<PT2, T, IsPT2,
|
|
UNION_DOESNT_CONTAIN_TYPE<T> > >::Return Ty;
|
|
int TyNo = Ty::Num;
|
|
return static_cast<int>(Val.getInt()) == TyNo;
|
|
}
|
|
|
|
/// get<T>() - Return the value of the specified pointer type. If the
|
|
/// specified pointer type is incorrect, assert.
|
|
template<typename T>
|
|
T get() const {
|
|
assert(is<T>() && "Invalid accessor called");
|
|
return PointerLikeTypeTraits<T>::getFromVoidPointer(Val.getPointer());
|
|
}
|
|
|
|
/// dyn_cast<T>() - If the current value is of the specified pointer type,
|
|
/// return it, otherwise return null.
|
|
template<typename T>
|
|
T dyn_cast() const {
|
|
if (is<T>()) return get<T>();
|
|
return T();
|
|
}
|
|
|
|
/// \brief If the union is set to the first pointer type get an address
|
|
/// pointing to it.
|
|
PT1 const *getAddrOfPtr1() const {
|
|
return const_cast<PointerUnion *>(this)->getAddrOfPtr1();
|
|
}
|
|
|
|
/// \brief If the union is set to the first pointer type get an address
|
|
/// pointing to it.
|
|
PT1 *getAddrOfPtr1() {
|
|
assert(is<PT1>() && "Val is not the first pointer");
|
|
assert(get<PT1>() == Val.getPointer() &&
|
|
"Can't get the address because PointerLikeTypeTraits changes the ptr");
|
|
return (PT1 *)Val.getAddrOfPointer();
|
|
}
|
|
|
|
/// Assignment operators - Allow assigning into this union from either
|
|
/// pointer type, setting the discriminator to remember what it came from.
|
|
const PointerUnion &operator=(const PT1 &RHS) {
|
|
Val.initWithPointer(
|
|
const_cast<void *>(PointerLikeTypeTraits<PT1>::getAsVoidPointer(RHS)));
|
|
return *this;
|
|
}
|
|
const PointerUnion &operator=(const PT2 &RHS) {
|
|
Val.setPointerAndInt(
|
|
const_cast<void *>(PointerLikeTypeTraits<PT2>::getAsVoidPointer(RHS)),
|
|
1);
|
|
return *this;
|
|
}
|
|
|
|
void *getOpaqueValue() const { return Val.getOpaqueValue(); }
|
|
static inline PointerUnion getFromOpaqueValue(void *VP) {
|
|
PointerUnion V;
|
|
V.Val = ValTy::getFromOpaqueValue(VP);
|
|
return V;
|
|
}
|
|
};
|
|
|
|
template<typename PT1, typename PT2>
|
|
static bool operator==(PointerUnion<PT1, PT2> lhs,
|
|
PointerUnion<PT1, PT2> rhs) {
|
|
return lhs.getOpaqueValue() == rhs.getOpaqueValue();
|
|
}
|
|
|
|
template<typename PT1, typename PT2>
|
|
static bool operator!=(PointerUnion<PT1, PT2> lhs,
|
|
PointerUnion<PT1, PT2> rhs) {
|
|
return lhs.getOpaqueValue() != rhs.getOpaqueValue();
|
|
}
|
|
|
|
// Teach SmallPtrSet that PointerUnion is "basically a pointer", that has
|
|
// # low bits available = min(PT1bits,PT2bits)-1.
|
|
template<typename PT1, typename PT2>
|
|
class PointerLikeTypeTraits<PointerUnion<PT1, PT2> > {
|
|
public:
|
|
static inline void *
|
|
getAsVoidPointer(const PointerUnion<PT1, PT2> &P) {
|
|
return P.getOpaqueValue();
|
|
}
|
|
static inline PointerUnion<PT1, PT2>
|
|
getFromVoidPointer(void *P) {
|
|
return PointerUnion<PT1, PT2>::getFromOpaqueValue(P);
|
|
}
|
|
|
|
// The number of bits available are the min of the two pointer types.
|
|
enum {
|
|
NumLowBitsAvailable =
|
|
PointerLikeTypeTraits<typename PointerUnion<PT1,PT2>::ValTy>
|
|
::NumLowBitsAvailable
|
|
};
|
|
};
|
|
|
|
|
|
/// PointerUnion3 - This is a pointer union of three pointer types. See
|
|
/// documentation for PointerUnion for usage.
|
|
template <typename PT1, typename PT2, typename PT3>
|
|
class PointerUnion3 {
|
|
public:
|
|
typedef PointerUnion<PT1, PT2> InnerUnion;
|
|
typedef PointerUnion<InnerUnion, PT3> ValTy;
|
|
private:
|
|
ValTy Val;
|
|
|
|
struct IsInnerUnion {
|
|
ValTy Val;
|
|
IsInnerUnion(ValTy val) : Val(val) { }
|
|
template<typename T>
|
|
int is() const {
|
|
return Val.template is<InnerUnion>() &&
|
|
Val.template get<InnerUnion>().template is<T>();
|
|
}
|
|
template<typename T>
|
|
T get() const {
|
|
return Val.template get<InnerUnion>().template get<T>();
|
|
}
|
|
};
|
|
|
|
struct IsPT3 {
|
|
ValTy Val;
|
|
IsPT3(ValTy val) : Val(val) { }
|
|
template<typename T>
|
|
int is() const {
|
|
return Val.template is<T>();
|
|
}
|
|
template<typename T>
|
|
T get() const {
|
|
return Val.template get<T>();
|
|
}
|
|
};
|
|
|
|
public:
|
|
PointerUnion3() {}
|
|
|
|
PointerUnion3(PT1 V) {
|
|
Val = InnerUnion(V);
|
|
}
|
|
PointerUnion3(PT2 V) {
|
|
Val = InnerUnion(V);
|
|
}
|
|
PointerUnion3(PT3 V) {
|
|
Val = V;
|
|
}
|
|
|
|
/// isNull - Return true if the pointer held in the union is null,
|
|
/// regardless of which type it is.
|
|
bool isNull() const { return Val.isNull(); }
|
|
LLVM_EXPLICIT operator bool() const { return !isNull(); }
|
|
|
|
/// is<T>() return true if the Union currently holds the type matching T.
|
|
template<typename T>
|
|
int is() const {
|
|
// If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3.
|
|
typedef typename
|
|
::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion,
|
|
::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 >
|
|
>::Return Ty;
|
|
return Ty(Val).template is<T>();
|
|
}
|
|
|
|
/// get<T>() - Return the value of the specified pointer type. If the
|
|
/// specified pointer type is incorrect, assert.
|
|
template<typename T>
|
|
T get() const {
|
|
assert(is<T>() && "Invalid accessor called");
|
|
// If T is PT1/PT2 choose IsInnerUnion otherwise choose IsPT3.
|
|
typedef typename
|
|
::llvm::PointerUnionTypeSelector<PT1, T, IsInnerUnion,
|
|
::llvm::PointerUnionTypeSelector<PT2, T, IsInnerUnion, IsPT3 >
|
|
>::Return Ty;
|
|
return Ty(Val).template get<T>();
|
|
}
|
|
|
|
/// dyn_cast<T>() - If the current value is of the specified pointer type,
|
|
/// return it, otherwise return null.
|
|
template<typename T>
|
|
T dyn_cast() const {
|
|
if (is<T>()) return get<T>();
|
|
return T();
|
|
}
|
|
|
|
/// Assignment operators - Allow assigning into this union from either
|
|
/// pointer type, setting the discriminator to remember what it came from.
|
|
const PointerUnion3 &operator=(const PT1 &RHS) {
|
|
Val = InnerUnion(RHS);
|
|
return *this;
|
|
}
|
|
const PointerUnion3 &operator=(const PT2 &RHS) {
|
|
Val = InnerUnion(RHS);
|
|
return *this;
|
|
}
|
|
const PointerUnion3 &operator=(const PT3 &RHS) {
|
|
Val = RHS;
|
|
return *this;
|
|
}
|
|
|
|
void *getOpaqueValue() const { return Val.getOpaqueValue(); }
|
|
static inline PointerUnion3 getFromOpaqueValue(void *VP) {
|
|
PointerUnion3 V;
|
|
V.Val = ValTy::getFromOpaqueValue(VP);
|
|
return V;
|
|
}
|
|
};
|
|
|
|
// Teach SmallPtrSet that PointerUnion3 is "basically a pointer", that has
|
|
// # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
|
|
template<typename PT1, typename PT2, typename PT3>
|
|
class PointerLikeTypeTraits<PointerUnion3<PT1, PT2, PT3> > {
|
|
public:
|
|
static inline void *
|
|
getAsVoidPointer(const PointerUnion3<PT1, PT2, PT3> &P) {
|
|
return P.getOpaqueValue();
|
|
}
|
|
static inline PointerUnion3<PT1, PT2, PT3>
|
|
getFromVoidPointer(void *P) {
|
|
return PointerUnion3<PT1, PT2, PT3>::getFromOpaqueValue(P);
|
|
}
|
|
|
|
// The number of bits available are the min of the two pointer types.
|
|
enum {
|
|
NumLowBitsAvailable =
|
|
PointerLikeTypeTraits<typename PointerUnion3<PT1, PT2, PT3>::ValTy>
|
|
::NumLowBitsAvailable
|
|
};
|
|
};
|
|
|
|
/// PointerUnion4 - This is a pointer union of four pointer types. See
|
|
/// documentation for PointerUnion for usage.
|
|
template <typename PT1, typename PT2, typename PT3, typename PT4>
|
|
class PointerUnion4 {
|
|
public:
|
|
typedef PointerUnion<PT1, PT2> InnerUnion1;
|
|
typedef PointerUnion<PT3, PT4> InnerUnion2;
|
|
typedef PointerUnion<InnerUnion1, InnerUnion2> ValTy;
|
|
private:
|
|
ValTy Val;
|
|
public:
|
|
PointerUnion4() {}
|
|
|
|
PointerUnion4(PT1 V) {
|
|
Val = InnerUnion1(V);
|
|
}
|
|
PointerUnion4(PT2 V) {
|
|
Val = InnerUnion1(V);
|
|
}
|
|
PointerUnion4(PT3 V) {
|
|
Val = InnerUnion2(V);
|
|
}
|
|
PointerUnion4(PT4 V) {
|
|
Val = InnerUnion2(V);
|
|
}
|
|
|
|
/// isNull - Return true if the pointer held in the union is null,
|
|
/// regardless of which type it is.
|
|
bool isNull() const { return Val.isNull(); }
|
|
LLVM_EXPLICIT operator bool() const { return !isNull(); }
|
|
|
|
/// is<T>() return true if the Union currently holds the type matching T.
|
|
template<typename T>
|
|
int is() const {
|
|
// If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2.
|
|
typedef typename
|
|
::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1,
|
|
::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 >
|
|
>::Return Ty;
|
|
return Val.template is<Ty>() &&
|
|
Val.template get<Ty>().template is<T>();
|
|
}
|
|
|
|
/// get<T>() - Return the value of the specified pointer type. If the
|
|
/// specified pointer type is incorrect, assert.
|
|
template<typename T>
|
|
T get() const {
|
|
assert(is<T>() && "Invalid accessor called");
|
|
// If T is PT1/PT2 choose InnerUnion1 otherwise choose InnerUnion2.
|
|
typedef typename
|
|
::llvm::PointerUnionTypeSelector<PT1, T, InnerUnion1,
|
|
::llvm::PointerUnionTypeSelector<PT2, T, InnerUnion1, InnerUnion2 >
|
|
>::Return Ty;
|
|
return Val.template get<Ty>().template get<T>();
|
|
}
|
|
|
|
/// dyn_cast<T>() - If the current value is of the specified pointer type,
|
|
/// return it, otherwise return null.
|
|
template<typename T>
|
|
T dyn_cast() const {
|
|
if (is<T>()) return get<T>();
|
|
return T();
|
|
}
|
|
|
|
/// Assignment operators - Allow assigning into this union from either
|
|
/// pointer type, setting the discriminator to remember what it came from.
|
|
const PointerUnion4 &operator=(const PT1 &RHS) {
|
|
Val = InnerUnion1(RHS);
|
|
return *this;
|
|
}
|
|
const PointerUnion4 &operator=(const PT2 &RHS) {
|
|
Val = InnerUnion1(RHS);
|
|
return *this;
|
|
}
|
|
const PointerUnion4 &operator=(const PT3 &RHS) {
|
|
Val = InnerUnion2(RHS);
|
|
return *this;
|
|
}
|
|
const PointerUnion4 &operator=(const PT4 &RHS) {
|
|
Val = InnerUnion2(RHS);
|
|
return *this;
|
|
}
|
|
|
|
void *getOpaqueValue() const { return Val.getOpaqueValue(); }
|
|
static inline PointerUnion4 getFromOpaqueValue(void *VP) {
|
|
PointerUnion4 V;
|
|
V.Val = ValTy::getFromOpaqueValue(VP);
|
|
return V;
|
|
}
|
|
};
|
|
|
|
// Teach SmallPtrSet that PointerUnion4 is "basically a pointer", that has
|
|
// # low bits available = min(PT1bits,PT2bits,PT2bits)-2.
|
|
template<typename PT1, typename PT2, typename PT3, typename PT4>
|
|
class PointerLikeTypeTraits<PointerUnion4<PT1, PT2, PT3, PT4> > {
|
|
public:
|
|
static inline void *
|
|
getAsVoidPointer(const PointerUnion4<PT1, PT2, PT3, PT4> &P) {
|
|
return P.getOpaqueValue();
|
|
}
|
|
static inline PointerUnion4<PT1, PT2, PT3, PT4>
|
|
getFromVoidPointer(void *P) {
|
|
return PointerUnion4<PT1, PT2, PT3, PT4>::getFromOpaqueValue(P);
|
|
}
|
|
|
|
// The number of bits available are the min of the two pointer types.
|
|
enum {
|
|
NumLowBitsAvailable =
|
|
PointerLikeTypeTraits<typename PointerUnion4<PT1, PT2, PT3, PT4>::ValTy>
|
|
::NumLowBitsAvailable
|
|
};
|
|
};
|
|
}
|
|
|
|
#endif
|