@@ -119,6 +119,85 @@ class ReflectionContext
119119 return getMetadataTypeInfo (MetadataAddress.second );
120120 }
121121
122+ bool
123+ projectExistential (RemoteAddress ExistentialAddress,
124+ const TypeRef *ExistentialTR,
125+ const TypeRef **OutInstanceTR,
126+ RemoteAddress *OutInstanceAddress) {
127+ if (ExistentialTR == nullptr )
128+ return false ;
129+
130+ auto ExistentialTI = getTypeInfo (ExistentialTR);
131+ if (ExistentialTI == nullptr )
132+ return false ;
133+
134+ auto ExistentialRecordTI = dyn_cast<const RecordTypeInfo>(ExistentialTI);
135+ if (ExistentialRecordTI == nullptr )
136+ return false ;
137+
138+ switch (ExistentialRecordTI->getRecordKind ()) {
139+ // Class existentials have trivial layout.
140+ // It is itself the pointer to the instance followed by the witness tables.
141+ case RecordKind::ClassExistential:
142+ *OutInstanceTR = getBuilder ().getTypeConverter ().getUnknownObjectTypeRef ();
143+ *OutInstanceAddress = ExistentialAddress;
144+ return true ;
145+
146+ // Other existentials have two cases:
147+ // If the value fits in three words, it starts at the beginning of the
148+ // container. If it doesn't, the first word is a pointer to a heap box.
149+ case RecordKind::Existential: {
150+ auto Fields = ExistentialRecordTI->getFields ();
151+ auto ExistentialMetadataField = std::find_if (Fields.begin (), Fields.end (),
152+ [](const FieldInfo &FI) -> bool {
153+ return FI.Name .compare (" metadata" ) == 0 ;
154+ });
155+ if (ExistentialMetadataField == Fields.end ())
156+ return false ;
157+
158+ // Get the metadata pointer for the contained instance type.
159+ // This is equivalent to:
160+ // auto PointerArray = reinterpret_cast<uintptr_t*>(ExistentialAddress);
161+ // uintptr_t MetadataAddress = PointerArray[Offset];
162+ auto MetadataAddressAddress
163+ = RemoteAddress (ExistentialAddress.getAddressData () +
164+ ExistentialMetadataField->Offset );
165+
166+ StoredPointer MetadataAddress = 0 ;
167+ if (!getReader ().readInteger (MetadataAddressAddress, &MetadataAddress))
168+ return false ;
169+
170+ auto InstanceTR = readTypeFromMetadata (MetadataAddress);
171+ if (!InstanceTR)
172+ return false ;
173+
174+ *OutInstanceTR = InstanceTR;
175+
176+ auto InstanceTI = getTypeInfo (InstanceTR);
177+ if (!InstanceTI)
178+ return false ;
179+
180+ if (InstanceTI->getSize () <= ExistentialMetadataField->Offset ) {
181+ // The value fits in the existential container, so it starts at the
182+ // start of the container.
183+ *OutInstanceAddress = ExistentialAddress;
184+ } else {
185+ // Otherwise it's in a box somewhere off in the heap. The first word
186+ // of the container has the address to that box.
187+ StoredPointer BoxAddress = 0 ;
188+
189+ if (!getReader ().readInteger (ExistentialAddress, &BoxAddress))
190+ return false ;
191+
192+ *OutInstanceAddress = RemoteAddress (BoxAddress);
193+ }
194+ return true ;
195+ }
196+ default :
197+ return false ;
198+ }
199+ }
200+
122201 // / Return a description of the layout of a value with the given type.
123202 const TypeInfo *getTypeInfo (const TypeRef *TR) {
124203 return getBuilder ().getTypeConverter ().getTypeInfo (TR);
0 commit comments