diff --git a/llvm/include/llvm/ADT/PointerIntPair.h b/llvm/include/llvm/ADT/PointerIntPair.h --- a/llvm/include/llvm/ADT/PointerIntPair.h +++ b/llvm/include/llvm/ADT/PointerIntPair.h @@ -127,6 +127,36 @@ } }; +namespace detail { +template struct ForceLowBitsPointerTraits { + using Base = llvm::PointerLikeTypeTraits; + static_assert(Bits <= Base::NumLowBitsAvailable, + "Too many bits specified for Base Traits"); + + static inline void *getAsVoidPointer(T P) { + return Base::getAsVoidPointer(P); + } + static inline T getFromVoidPointer(void *P) { + return Base::getFromVoidPointer(P); + } + + static constexpr int NumLowBitsAvailable = Bits; +}; +} // namespace detail + +/// LowPointerIntPair - This is a \ref PointerIntPair that stores the IntVal in +/// the lowest bits. This removes the need for shifts when accessing the stored +/// IntVal. As it is using the lowest bits, this can't be used as a PointerType +/// inside a nested PointerIntPair. However it can have nested PointerIntPairs +/// used as its own PointerType, like this: +/// LowPointerIntPair, 1> +/// LowPointerIntPair will use bit #0, +/// PointerIntPair will use bit #1 or #2 depending on alignment of void*. +template +using LowPointerIntPair = + PointerIntPair>; + // Specialize is_trivially_copyable to avoid limitation of llvm::is_trivially_copyable // when compiled with gcc 4.9. template >::NumLowBitsAvailable == 0, + "Using LowestBits"); + + // Use double as guaranteed 8 byte alignment on 32 or 64 bit, meaning 3 bits + // to play with. + LowPointerIntPair, 1, bool> P; + // Ensure they are both using different bits, and that the LowPointerIntPair + // is using the LSB. + P.setPointerAndInt({nullptr, true}, false); + EXPECT_EQ(reinterpret_cast(P.getOpaqueValue()), 0b100U); + P.setInt(true); + EXPECT_EQ(reinterpret_cast(P.getOpaqueValue()), 0b101U); + auto Nested = P.getPointer(); + Nested.setInt(false); + P.setPointer(Nested); + EXPECT_EQ(reinterpret_cast(P.getOpaqueValue()), 0b001U); +} + } // end anonymous namespace