@@ -86,6 +86,26 @@ struct delete_with_free {
86
86
}
87
87
};
88
88
89
+ // / A structure representing an opened existential type.
90
+ struct RemoteExistential {
91
+ // / The payload's concrete type metadata.
92
+ RemoteAddress MetadataAddress;
93
+
94
+ // / The address of the payload value.
95
+ RemoteAddress PayloadAddress;
96
+
97
+ // / True if this is an NSError instance transparently bridged to an Error
98
+ // / existential.
99
+ bool IsBridgedError;
100
+
101
+ RemoteExistential (RemoteAddress MetadataAddress,
102
+ RemoteAddress PayloadAddress,
103
+ bool IsBridgedError=false )
104
+ : MetadataAddress(MetadataAddress),
105
+ PayloadAddress (PayloadAddress),
106
+ IsBridgedError(IsBridgedError) {}
107
+ };
108
+
89
109
// / A generic reader of metadata.
90
110
// /
91
111
// / BuilderType must implement a particular interface which is currently
@@ -327,8 +347,10 @@ class MetadataReader {
327
347
}
328
348
329
349
// / Given a pointer to a known-error existential, attempt to discover the
330
- // / pointer to its metadata address and its value address.
331
- Optional<std::pair<RemoteAddress, RemoteAddress>>
350
+ // / pointer to its metadata address, its value address, and whether this
351
+ // / is a toll-free-bridged NSError or an actual Error existential wrapper
352
+ // / around a native Swift value.
353
+ Optional<RemoteExistential>
332
354
readMetadataAndValueErrorExistential (RemoteAddress ExistentialAddress) {
333
355
// An pointer to an error existential is always an heap object.
334
356
auto MetadataAddress =
@@ -337,13 +359,16 @@ class MetadataReader {
337
359
return None;
338
360
339
361
bool isObjC = false ;
362
+ bool isBridged = false ;
340
363
341
364
// If we can determine the Objective-C class name, this is probably an
342
365
// error existential with NSError-compatible layout.
343
366
std::string ObjCClassName;
344
367
if (readObjCClassName (*MetadataAddress, ObjCClassName)) {
345
368
if (ObjCClassName == " __SwiftNativeNSError" )
346
369
isObjC = true ;
370
+ else
371
+ isBridged = true ;
347
372
} else {
348
373
// Otherwise, we can check to see if this is a class metadata with the
349
374
// kind value's least significant bit set, which indicates a pure
@@ -356,6 +381,13 @@ class MetadataReader {
356
381
isObjC = ClassMeta->isPureObjC ();
357
382
}
358
383
384
+ if (isBridged) {
385
+ // NSError instances don't need to be unwrapped.
386
+ return RemoteExistential (RemoteAddress (*MetadataAddress),
387
+ ExistentialAddress,
388
+ isBridged);
389
+ }
390
+
359
391
// In addition to the isa pointer and two 32-bit reference counts, if the
360
392
// error existential is layout-compatible with NSError, we also need to
361
393
// skip over its three word-sized fields: the error code, the domain,
@@ -387,14 +419,15 @@ class MetadataReader {
387
419
auto Offset = (sizeof (HeapObject) + AlignmentMask) & ~AlignmentMask;
388
420
InstanceAddress += Offset;
389
421
390
- return Optional<std::pair<RemoteAddress, RemoteAddress>>(
391
- {RemoteAddress (*InstanceMetadataAddress),
392
- RemoteAddress (InstanceAddress)});
422
+ return RemoteExistential (
423
+ RemoteAddress (*InstanceMetadataAddress),
424
+ RemoteAddress (InstanceAddress),
425
+ isBridged);
393
426
}
394
427
395
428
// / Given a known-opaque existential, attemp to discover the pointer to its
396
429
// / metadata address and its value.
397
- Optional<std::pair<RemoteAddress, RemoteAddress> >
430
+ Optional<RemoteExistential >
398
431
readMetadataAndValueOpaqueExistential (RemoteAddress ExistentialAddress) {
399
432
// OpaqueExistentialContainer is the layout of an opaque existential.
400
433
// `Type` is the pointer to the metadata.
@@ -414,8 +447,8 @@ class MetadataReader {
414
447
// Inline representation (the value fits in the existential container).
415
448
// So, the value starts at the first word of the container.
416
449
if (VWT->isValueInline ())
417
- return Optional<std::pair< RemoteAddress, RemoteAddress>>(
418
- { RemoteAddress (MetadataAddress), ExistentialAddress} );
450
+ return RemoteExistential ( RemoteAddress (MetadataAddress),
451
+ ExistentialAddress);
419
452
420
453
// Non-inline (box'ed) representation.
421
454
// The first word of the container stores the address to the box.
@@ -426,8 +459,8 @@ class MetadataReader {
426
459
auto AlignmentMask = VWT->getAlignmentMask ();
427
460
auto Offset = (sizeof (HeapObject) + AlignmentMask) & ~AlignmentMask;
428
461
auto StartOfValue = BoxAddress + Offset;
429
- return Optional<std::pair< RemoteAddress, RemoteAddress>>(
430
- { RemoteAddress (MetadataAddress), RemoteAddress (StartOfValue)} );
462
+ return RemoteExistential ( RemoteAddress (MetadataAddress),
463
+ RemoteAddress (StartOfValue));
431
464
}
432
465
433
466
// / Read a protocol from a reference to said protocol.
@@ -496,28 +529,8 @@ class MetadataReader {
496
529
if (!Meta) return BuiltType ();
497
530
498
531
switch (Meta->getKind ()) {
499
- case MetadataKind::Class: {
500
- auto classMeta = cast<TargetClassMetadata<Runtime>>(Meta);
501
- if (!classMeta->isTypeMetadata ()) {
502
- std::string className;
503
- if (!readObjCClassName (MetadataAddress, className))
504
- return BuiltType ();
505
-
506
- BuiltType BuiltObjCClass = Builder.createObjCClassType (std::move (className));
507
- if (!BuiltObjCClass) {
508
- // Try the superclass.
509
- if (!classMeta->Superclass )
510
- return BuiltType ();
511
-
512
- BuiltObjCClass = readTypeFromMetadata (classMeta->Superclass ,
513
- skipArtificialSubclasses);
514
- }
515
-
516
- TypeCache[MetadataAddress] = BuiltObjCClass;
517
- return BuiltObjCClass;
518
- }
519
- return readNominalTypeFromMetadata (Meta, skipArtificialSubclasses);
520
- }
532
+ case MetadataKind::Class:
533
+ return readNominalTypeFromClassMetadata (Meta, skipArtificialSubclasses);
521
534
case MetadataKind::Struct:
522
535
case MetadataKind::Enum:
523
536
case MetadataKind::Optional:
@@ -2283,6 +2296,30 @@ class MetadataReader {
2283
2296
return nominal;
2284
2297
}
2285
2298
2299
+ BuiltType readNominalTypeFromClassMetadata (MetadataRef origMetadata,
2300
+ bool skipArtificialSubclasses = false ) {
2301
+ auto classMeta = cast<TargetClassMetadata<Runtime>>(origMetadata);
2302
+ if (classMeta->isTypeMetadata ())
2303
+ return readNominalTypeFromMetadata (origMetadata, skipArtificialSubclasses);
2304
+
2305
+ std::string className;
2306
+ if (!readObjCClassName (origMetadata.getAddress (), className))
2307
+ return BuiltType ();
2308
+
2309
+ BuiltType BuiltObjCClass = Builder.createObjCClassType (std::move (className));
2310
+ if (!BuiltObjCClass) {
2311
+ // Try the superclass.
2312
+ if (!classMeta->Superclass )
2313
+ return BuiltType ();
2314
+
2315
+ BuiltObjCClass = readTypeFromMetadata (classMeta->Superclass ,
2316
+ skipArtificialSubclasses);
2317
+ }
2318
+
2319
+ TypeCache[origMetadata.getAddress ()] = BuiltObjCClass;
2320
+ return BuiltObjCClass;
2321
+ }
2322
+
2286
2323
// / Given that the remote process is running the non-fragile Apple runtime,
2287
2324
// / grab the ro-data from a class pointer.
2288
2325
StoredPointer readObjCRODataPtr (StoredPointer classAddress) {
0 commit comments