20
20
21
21
#include " swift/AST/PlatformKind.h"
22
22
#include " swift/Basic/LLVM.h"
23
+ #include " llvm/ADT/PointerEmbeddedInt.h"
24
+ #include " llvm/ADT/PointerUnion.h"
23
25
24
26
namespace swift {
25
27
class ASTContext ;
@@ -44,17 +46,66 @@ class AvailabilityDomain final {
44
46
};
45
47
46
48
private:
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
+ };
49
81
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()) {
51
92
assert (kind != Kind::Platform);
52
93
};
53
94
54
95
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
+ }
58
109
59
110
public:
60
111
AvailabilityDomain () {}
@@ -75,18 +126,30 @@ class AvailabilityDomain final {
75
126
return AvailabilityDomain (Kind::PackageDescription);
76
127
}
77
128
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
+ }
79
135
80
- bool isUniversal () const { return kind == Kind::Universal; }
136
+ bool isUniversal () const { return getKind () == Kind::Universal; }
81
137
82
- bool isPlatform () const { return kind == Kind::Platform; }
138
+ bool isPlatform () const { return getKind () == Kind::Platform; }
83
139
84
- bool isSwiftLanguage () const { return kind == Kind::SwiftLanguage; }
140
+ bool isSwiftLanguage () const { return getKind () == Kind::SwiftLanguage; }
85
141
86
- bool isPackageDescription () const { return kind == Kind::PackageDescription; }
142
+ bool isPackageDescription () const {
143
+ return getKind () == Kind::PackageDescription;
144
+ }
87
145
88
146
// / 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
+ }
90
153
91
154
// / Returns true if this domain is considered active in the current
92
155
// / compilation context.
@@ -136,4 +199,25 @@ class AvailabilityDomain final {
136
199
137
200
} // end namespace swift
138
201
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
+
139
223
#endif
0 commit comments