2020
2121#include " swift/AST/PlatformKind.h"
2222#include " swift/Basic/LLVM.h"
23+ #include " llvm/ADT/PointerEmbeddedInt.h"
24+ #include " llvm/ADT/PointerUnion.h"
2325
2426namespace swift {
2527class ASTContext ;
@@ -44,17 +46,66 @@ class AvailabilityDomain final {
4446 };
4547
4648private:
47- Kind kind;
48- PlatformKind platform;
49+ friend struct llvm ::PointerLikeTypeTraits<AvailabilityDomain>;
50+
51+ // / For a subset of domain kinds, all the information needed to represent the
52+ // / domain can be encapsulated inline in this class.
53+ class InlineDomain {
54+ Kind kind;
55+ PlatformKind platform;
56+
57+ public:
58+ using IntReprType = uint32_t ;
59+ enum : uintptr_t {
60+ ReprBits = sizeof (IntReprType) * CHAR_BIT - 8 ,
61+ KindShift = ReprBits - sizeof (Kind) * CHAR_BIT,
62+ PlatformShift = KindShift - sizeof (PlatformKind) * CHAR_BIT,
63+ };
64+
65+ InlineDomain (Kind kind, PlatformKind platform)
66+ : kind(kind), platform(platform) {};
67+ InlineDomain (IntReprType value)
68+ : kind(static_cast <Kind>(value >> KindShift)),
69+ platform (static_cast <PlatformKind>(value >> PlatformShift)) {}
70+
71+ // / Serializes the domain into an integer value that must be smaller than a
72+ // / a pointer.
73+ IntReprType asInteger () const {
74+ return static_cast <IntReprType>(kind) << KindShift |
75+ static_cast <IntReprType>(platform) << PlatformShift;
76+ }
77+
78+ Kind getKind () const { return kind; }
79+ PlatformKind getPlatform () { return platform; }
80+ };
4981
50- AvailabilityDomain (Kind kind) : kind(kind), platform(PlatformKind::none) {
82+ // / This will eventually be a class storing information about externally
83+ // / defined availability domains.
84+ using ExternalDomain = void ;
85+
86+ using InlineDomainPtr = llvm::PointerEmbeddedInt<uint32_t , InlineDomain::ReprBits>;
87+ using Storage = llvm::PointerUnion<ExternalDomain *, InlineDomainPtr>;
88+ Storage storage;
89+
90+ AvailabilityDomain (Kind kind)
91+ : storage(InlineDomain(kind, PlatformKind::none).asInteger()) {
5192 assert (kind != Kind::Platform);
5293 };
5394
5495 AvailabilityDomain (PlatformKind platform)
55- : kind(Kind::Platform), platform(platform) {
56- assert (platform != PlatformKind::none);
57- };
96+ : storage(InlineDomain(Kind::Platform, platform).asInteger()) {};
97+
98+ AvailabilityDomain (void *opaque)
99+ : storage(Storage::getFromOpaqueValue(opaque)) {};
100+
101+ void *getOpaqueValue () const { return storage.getOpaqueValue (); }
102+
103+ std::optional<InlineDomain> getInlineDomain () const {
104+ return storage.is <InlineDomainPtr>()
105+ ? static_cast <std::optional<InlineDomain>>(
106+ storage.get <InlineDomainPtr>())
107+ : std::nullopt ;
108+ }
58109
59110public:
60111 AvailabilityDomain () {}
@@ -75,18 +126,30 @@ class AvailabilityDomain final {
75126 return AvailabilityDomain (Kind::PackageDescription);
76127 }
77128
78- Kind getKind () const { return kind; }
129+ Kind getKind () const {
130+ if (auto inlineDomain = getInlineDomain ())
131+ return inlineDomain->getKind ();
132+
133+ llvm_unreachable (" unimplemented" );
134+ }
79135
80- bool isUniversal () const { return kind == Kind::Universal; }
136+ bool isUniversal () const { return getKind () == Kind::Universal; }
81137
82- bool isPlatform () const { return kind == Kind::Platform; }
138+ bool isPlatform () const { return getKind () == Kind::Platform; }
83139
84- bool isSwiftLanguage () const { return kind == Kind::SwiftLanguage; }
140+ bool isSwiftLanguage () const { return getKind () == Kind::SwiftLanguage; }
85141
86- bool isPackageDescription () const { return kind == Kind::PackageDescription; }
142+ bool isPackageDescription () const {
143+ return getKind () == Kind::PackageDescription;
144+ }
87145
88146 // / Returns the platform kind for this domain if applicable.
89- PlatformKind getPlatformKind () const { return platform; }
147+ PlatformKind getPlatformKind () const {
148+ if (auto inlineDomain = getInlineDomain ())
149+ return inlineDomain->getPlatform ();
150+
151+ return PlatformKind::none;
152+ }
90153
91154 // / Returns true if this domain is considered active in the current
92155 // / compilation context.
@@ -136,4 +199,25 @@ class AvailabilityDomain final {
136199
137200} // end namespace swift
138201
202+ namespace llvm {
203+ // An AvailabilityDomain is "pointer like".
204+ template <typename T>
205+ struct PointerLikeTypeTraits ;
206+ template <>
207+ struct PointerLikeTypeTraits <swift::AvailabilityDomain> {
208+ public:
209+ static inline void *getAsVoidPointer (swift::AvailabilityDomain domain) {
210+ return domain.storage .getOpaqueValue ();
211+ }
212+ static inline swift::AvailabilityDomain getFromVoidPointer (void *P) {
213+ return swift::AvailabilityDomain (P);
214+ }
215+ enum {
216+ NumLowBitsAvailable = PointerLikeTypeTraits<
217+ swift::AvailabilityDomain::Storage>::NumLowBitsAvailable
218+ };
219+ };
220+
221+ } // end namespace llvm
222+
139223#endif
0 commit comments