2020#include " PrebuiltStringMap.h"
2121#include " swift/ABI/Metadata.h"
2222#include " swift/ABI/TargetLayout.h"
23+ #include " swift/Demangling/Demangler.h"
2324
2425#define LIB_PRESPECIALIZED_TOP_LEVEL_SYMBOL_NAME " _swift_prespecializationsData"
2526
@@ -36,23 +37,44 @@ struct LibPrespecializedData {
3637
3738 typename Runtime::StoredSize optionFlags;
3839
40+ TargetPointer<Runtime, const void > descriptorMap;
41+
3942 // Existing fields are above, add new fields below this point.
4043
44+ // The major/minor version numbers for this version of the struct.
4145 static constexpr uint32_t currentMajorVersion = 1 ;
42- static constexpr uint32_t currentMinorVersion = 3 ;
46+ static constexpr uint32_t currentMinorVersion = 4 ;
4347
48+ // Version numbers where various fields were introduced.
4449 static constexpr uint32_t minorVersionWithDisabledProcessesTable = 2 ;
4550 static constexpr uint32_t minorVersionWithPointerKeyedMetadataMap = 3 ;
4651 static constexpr uint32_t minorVersionWithOptionFlags = 3 ;
52+ static constexpr uint32_t minorVersionWithDescriptorMap = 4 ;
4753
4854 // Option flags values.
4955 enum : typename Runtime::StoredSize {
5056 // When this flag is set, the runtime should default to using the
5157 // pointer-keyed table. When not set, default to using the name-keyed table.
5258 OptionFlagDefaultToPointerKeyedMap = 1ULL << 0 ,
59+
60+ // When this flag is set, the runtime should default to using the descriptor
61+ // map. When not set, default to turning off the descriptor map.
62+ OptionFlagDescriptorMapDefaultOn = 1ULL << 1 ,
63+
64+ // When this flag is set, descriptorMap is not comprehensive, meaning that
65+ // a negative lookup result is not a definitive failure.
66+ OptionFlagDescriptorMapNotComprehensive = 1ULL << 2 ,
5367 };
5468
55- // Helpers for retrieving the metadata map in-process.
69+ // Helpers for safely retrieving various fields. Helpers return 0 or NULL if
70+ // the version number indicates that the field is not present.
71+
72+ typename Runtime::StoredSize getOptionFlags () const {
73+ if (minorVersion < minorVersionWithOptionFlags)
74+ return 0 ;
75+ return optionFlags;
76+ }
77+
5678 static bool stringIsNull (const char *str) { return str == nullptr ; }
5779
5880 using MetadataMap = PrebuiltStringMap<const char *, Metadata *, stringIsNull>;
@@ -73,18 +95,141 @@ struct LibPrespecializedData {
7395 return pointerKeyedMetadataMap;
7496 }
7597
76- typename Runtime::StoredSize getOptionFlags () const {
77- if (minorVersion < minorVersionWithOptionFlags)
78- return 0 ;
79- return optionFlags;
98+ using DescriptorMap =
99+ PrebuiltAuxDataImplicitStringMap<TargetPointer<Runtime, const void >,
100+ uint16_t >;
101+
102+ const DescriptorMap *getDescriptorMap () const {
103+ if (minorVersion < minorVersionWithDescriptorMap)
104+ return nullptr ;
105+ return reinterpret_cast <const DescriptorMap *>(descriptorMap);
80106 }
81107};
82108
109+ enum class LibPrespecializedLookupResult {
110+ // We found something.
111+ Found,
112+
113+ // We didn't find anything, and we know it's not in the shared cache.
114+ DefinitiveNotFound,
115+
116+ // We didn't find anything, but we couldn't rule out the shared cache. Caller
117+ // must do a full search.
118+ NonDefinitiveNotFound,
119+ };
120+
83121const LibPrespecializedData<InProcess> *getLibPrespecializedData ();
122+
84123Metadata *getLibPrespecializedMetadata (const TypeContextDescriptor *description,
85124 const void *const *arguments);
86125void libPrespecializedImageLoaded ();
87126
127+ std::pair<LibPrespecializedLookupResult, const TypeContextDescriptor *>
128+ getLibPrespecializedTypeDescriptor (Demangle::NodePointer node);
129+
130+ // / Given the demangling referring to a particular descriptor, build the
131+ // / canonical simplified version of the demangling that's used for the keys in
132+ // / the descriptorMap. We copy across Extension and Module nodes. Type nodes are
133+ // / all normalized to be OtherNominalType to allow for the runtime allowing
134+ // / type kind mismatches on imported C types in certain cases. Other nodes are
135+ // / skipped.
136+ // /
137+ // / The runtime always searches through duplicates in the table, and uses its
138+ // / own matching on all candidates, so the simplified demangling is allowed to
139+ // / be simplified to the point of having different descriptors sometimes produce
140+ // / the same demangling.
141+ static inline Demangle::NodePointer
142+ buildSimplifiedDescriptorDemangling (Demangle::NodePointer node,
143+ Demangle::Demangler &dem) {
144+ // The node that will be returned to the caller.
145+ Demangle::NodePointer result = nullptr ;
146+
147+ // The bottommost node in the result that we've generated. Additional nodes
148+ // are added as children to this one.
149+ Demangle::NodePointer resultBottom = nullptr ;
150+
151+ // The current node that we're iterating over in the input node tree.
152+ Demangle::NodePointer current = node;
153+
154+ using Kind = Demangle::Node::Kind;
155+
156+ // Helper to add a new node to the result. This sets `result` to the node if
157+ // it hasn't already been set (indicating this is the topmost node), and adds
158+ // the node as a child to `resultBottom` otherwise. `resultBottom` is updated
159+ // to point to the new node.
160+ auto addNode = [&](Demangle::NodePointer newNode) {
161+ if (!result) {
162+ result = newNode;
163+ } else {
164+ if (resultBottom->getKind () == Kind::Extension) {
165+ resultBottom->addChild (newNode, dem);
166+ } else {
167+ // Shift the Identifier down, insert before it.
168+ resultBottom->addChild (resultBottom->getFirstChild (), dem);
169+ resultBottom->replaceChild (0 , newNode);
170+ }
171+ }
172+ resultBottom = newNode;
173+ };
174+
175+ // Walk down the input node tree.
176+ while (current) {
177+ switch (current->getKind ()) {
178+ case Kind::Extension: {
179+ // Extensions are copied across. The new extension node has the module
180+ // from the original, and the second child will be added as we traverse
181+ // the next node in the tree.
182+ auto copy = dem.createNode (Kind::Extension);
183+ auto module = current->getChild (0 );
184+ if (module == nullptr || module ->getKind () != Kind::Module)
185+ return nullptr ;
186+ copy->addChild (module , dem);
187+ addNode (copy);
188+ current = current->getChild (1 );
189+ break ;
190+ }
191+ case Kind::Module: {
192+ // Module contents are always in the form we want, so we can incorporate
193+ // this node verbatim and terminate the walk.
194+ addNode (current);
195+ current = nullptr ;
196+ break ;
197+ }
198+ case Kind::Protocol: {
199+ // Bring Protocol nodes across verbatim, there's no fuzzy matching.
200+ addNode (current);
201+ current = nullptr ;
202+ break ;
203+ }
204+ case Kind::OpaqueType:
205+ case Kind::Class:
206+ case Kind::Structure:
207+ case Kind::Enum:
208+ case Kind::TypeAlias:
209+ case Kind::OtherNominalType: {
210+ // Type nodes are copied across with the kind always set to
211+ // OtherNominalType.
212+ auto copy = dem.createNode (Kind::OtherNominalType);
213+ auto identifier = current->getChild (1 );
214+ if (identifier == nullptr || identifier->getKind () != Kind::Identifier)
215+ return nullptr ;
216+ copy->addChild (identifier, dem);
217+ addNode (copy);
218+ current = current->getChild (0 );
219+ break ;
220+ }
221+
222+ default :
223+ // If we don't know about this node, continue the walk with its first
224+ // child.
225+ current = current->getFirstChild ();
226+ break ;
227+ }
228+ }
229+
230+ return result;
231+ }
232+
88233} // namespace swift
89234
90235// Validate the prespecialized metadata map by building each entry dynamically
0 commit comments