Skip to content

Commit 2c7649f

Browse files
authored
Merge pull request #22502 from slavapestov/remote-ast-fixes
RemoteAST fixes
2 parents e840be0 + 905a6de commit 2c7649f

File tree

6 files changed

+200
-84
lines changed

6 files changed

+200
-84
lines changed

include/swift/Reflection/ReflectionContext.h

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -520,15 +520,14 @@ class ReflectionContext
520520
readMetadataAndValueOpaqueExistential(ExistentialAddress);
521521
if (!OptMetaAndValue)
522522
return false;
523-
RemoteAddress MetadataAddress = OptMetaAndValue->first;
524-
RemoteAddress ValueAddress = OptMetaAndValue->second;
525523

526-
auto InstanceTR = readTypeFromMetadata(MetadataAddress.getAddressData());
524+
auto InstanceTR = readTypeFromMetadata(
525+
OptMetaAndValue->MetadataAddress.getAddressData());
527526
if (!InstanceTR)
528527
return false;
529528

530529
*OutInstanceTR = InstanceTR;
531-
*OutInstanceAddress = ValueAddress;
530+
*OutInstanceAddress = OptMetaAndValue->PayloadAddress;
532531
return true;
533532
}
534533
case RecordKind::ErrorExistential: {
@@ -537,16 +536,15 @@ class ReflectionContext
537536
if (!OptMetaAndValue)
538537
return false;
539538

540-
RemoteAddress InstanceMetadataAddress = OptMetaAndValue->first;
541-
RemoteAddress InstanceAddress = OptMetaAndValue->second;
539+
// FIXME: Check third value, 'IsBridgedError'
542540

543-
auto InstanceTR =
544-
readTypeFromMetadata(InstanceMetadataAddress.getAddressData());
541+
auto InstanceTR = readTypeFromMetadata(
542+
OptMetaAndValue->MetadataAddress.getAddressData());
545543
if (!InstanceTR)
546544
return false;
547545

548546
*OutInstanceTR = InstanceTR;
549-
*OutInstanceAddress = RemoteAddress(InstanceAddress);
547+
*OutInstanceAddress = OptMetaAndValue->PayloadAddress;
550548
return true;
551549
}
552550
default:

include/swift/Remote/MetadataReader.h

Lines changed: 69 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,26 @@ struct delete_with_free {
8686
}
8787
};
8888

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+
89109
/// A generic reader of metadata.
90110
///
91111
/// BuilderType must implement a particular interface which is currently
@@ -327,8 +347,10 @@ class MetadataReader {
327347
}
328348

329349
/// 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>
332354
readMetadataAndValueErrorExistential(RemoteAddress ExistentialAddress) {
333355
// An pointer to an error existential is always an heap object.
334356
auto MetadataAddress =
@@ -337,13 +359,16 @@ class MetadataReader {
337359
return None;
338360

339361
bool isObjC = false;
362+
bool isBridged = false;
340363

341364
// If we can determine the Objective-C class name, this is probably an
342365
// error existential with NSError-compatible layout.
343366
std::string ObjCClassName;
344367
if (readObjCClassName(*MetadataAddress, ObjCClassName)) {
345368
if (ObjCClassName == "__SwiftNativeNSError")
346369
isObjC = true;
370+
else
371+
isBridged = true;
347372
} else {
348373
// Otherwise, we can check to see if this is a class metadata with the
349374
// kind value's least significant bit set, which indicates a pure
@@ -356,6 +381,13 @@ class MetadataReader {
356381
isObjC = ClassMeta->isPureObjC();
357382
}
358383

384+
if (isBridged) {
385+
// NSError instances don't need to be unwrapped.
386+
return RemoteExistential(RemoteAddress(*MetadataAddress),
387+
ExistentialAddress,
388+
isBridged);
389+
}
390+
359391
// In addition to the isa pointer and two 32-bit reference counts, if the
360392
// error existential is layout-compatible with NSError, we also need to
361393
// skip over its three word-sized fields: the error code, the domain,
@@ -387,14 +419,15 @@ class MetadataReader {
387419
auto Offset = (sizeof(HeapObject) + AlignmentMask) & ~AlignmentMask;
388420
InstanceAddress += Offset;
389421

390-
return Optional<std::pair<RemoteAddress, RemoteAddress>>(
391-
{RemoteAddress(*InstanceMetadataAddress),
392-
RemoteAddress(InstanceAddress)});
422+
return RemoteExistential(
423+
RemoteAddress(*InstanceMetadataAddress),
424+
RemoteAddress(InstanceAddress),
425+
isBridged);
393426
}
394427

395428
/// Given a known-opaque existential, attemp to discover the pointer to its
396429
/// metadata address and its value.
397-
Optional<std::pair<RemoteAddress, RemoteAddress>>
430+
Optional<RemoteExistential>
398431
readMetadataAndValueOpaqueExistential(RemoteAddress ExistentialAddress) {
399432
// OpaqueExistentialContainer is the layout of an opaque existential.
400433
// `Type` is the pointer to the metadata.
@@ -414,8 +447,8 @@ class MetadataReader {
414447
// Inline representation (the value fits in the existential container).
415448
// So, the value starts at the first word of the container.
416449
if (VWT->isValueInline())
417-
return Optional<std::pair<RemoteAddress, RemoteAddress>>(
418-
{RemoteAddress(MetadataAddress), ExistentialAddress});
450+
return RemoteExistential(RemoteAddress(MetadataAddress),
451+
ExistentialAddress);
419452

420453
// Non-inline (box'ed) representation.
421454
// The first word of the container stores the address to the box.
@@ -426,8 +459,8 @@ class MetadataReader {
426459
auto AlignmentMask = VWT->getAlignmentMask();
427460
auto Offset = (sizeof(HeapObject) + AlignmentMask) & ~AlignmentMask;
428461
auto StartOfValue = BoxAddress + Offset;
429-
return Optional<std::pair<RemoteAddress, RemoteAddress>>(
430-
{RemoteAddress(MetadataAddress), RemoteAddress(StartOfValue)});
462+
return RemoteExistential(RemoteAddress(MetadataAddress),
463+
RemoteAddress(StartOfValue));
431464
}
432465

433466
/// Read a protocol from a reference to said protocol.
@@ -496,28 +529,8 @@ class MetadataReader {
496529
if (!Meta) return BuiltType();
497530

498531
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);
521534
case MetadataKind::Struct:
522535
case MetadataKind::Enum:
523536
case MetadataKind::Optional:
@@ -2283,6 +2296,30 @@ class MetadataReader {
22832296
return nominal;
22842297
}
22852298

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+
22862323
/// Given that the remote process is running the non-fragile Apple runtime,
22872324
/// grab the ro-data from a class pointer.
22882325
StoredPointer readObjCRODataPtr(StoredPointer classAddress) {

include/swift/RemoteAST/RemoteAST.h

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "swift/Remote/MemoryReader.h"
2424
#include "swift/Basic/LLVM.h"
2525
#include "swift/ABI/MetadataValues.h"
26+
#include "swift/AST/Type.h"
2627
#include "llvm/ADT/Optional.h"
2728
#include "llvm/ADT/StringRef.h"
2829

@@ -31,7 +32,6 @@
3132
namespace swift {
3233
class ASTContext;
3334
class NominalTypeDecl;
34-
class Type;
3535

3636
namespace remoteAST {
3737

@@ -136,6 +136,21 @@ class Result {
136136
}
137137
};
138138

139+
/// A structure representing an opened existential value.
140+
struct OpenedExistential {
141+
/// The concrete type of the value inside the existential.
142+
Type InstanceType;
143+
144+
/// The address of the payload.
145+
///
146+
/// Note: If the concrete type is a class type, this is the address of the
147+
/// instance and not the address of the reference to the instance.
148+
remote::RemoteAddress PayloadAddress;
149+
150+
OpenedExistential(Type InstanceType, remote::RemoteAddress PayloadAddress)
151+
: InstanceType(InstanceType), PayloadAddress(PayloadAddress) {}
152+
};
153+
139154
/// A context for performing an operation relating the remote process with
140155
/// the AST. This may be discarded and recreated at any time without danger,
141156
/// but reusing a context across multiple calls may allow some redundant work
@@ -212,11 +227,17 @@ class RemoteASTContext {
212227
Result<remote::RemoteAddress>
213228
getHeapMetadataForObject(remote::RemoteAddress address);
214229

230+
/// Resolve the dynamic type and the value address of an error existential
231+
/// object, Unlike getDynamicTypeAndAddressForExistential(), this function
232+
/// takes the address of the instance and not the address of the reference.
233+
Result<OpenedExistential>
234+
getDynamicTypeAndAddressForError(remote::RemoteAddress object);
235+
215236
/// Given an existential and its static type, resolve its dynamic
216237
/// type and address. A single step of unwrapping is performed, i.e. if the
217238
/// value stored inside the existential is itself an existential, the
218239
/// caller can decide whether to iterate itself.
219-
Result<std::pair<Type, remote::RemoteAddress>>
240+
Result<OpenedExistential>
220241
getDynamicTypeAndAddressForExistential(remote::RemoteAddress address,
221242
Type staticType);
222243
};

0 commit comments

Comments
 (0)