Implement projectExistentialAndUnwrapClass

Implement a version of projectExistential tailored for LLDB. There are 2
differences when projecting existentials for LLDB:

1 - When it comes to existentials, LLDB stores the address of the error
    pointer, which must be dereferenced.
2 - When the existential wraps a class type, LLDB expects the address
    returned is the class instance itself and not the address of the
    reference.

This patch also adapts the swift reflection test machinery to test
projectExistentialAndUnwrapClass as well. This is done by exposing
the new functionality from swift reflection test.  It is tested in
existentials.swift, and ensures that the typeref information is
exactly the same as what is expected from projectExistential,
except the out address.

(cherry picked from commit 55e971e06750c3ba29722d558cc5400298f6bdaf)
This commit is contained in:
Augusto Noronha
2021-06-08 13:31:08 -03:00
parent 92beb71f8a
commit f41d192b48
7 changed files with 612 additions and 26 deletions

View File

@@ -92,7 +92,7 @@ class ReflectionContext
using super = remote::MetadataReader<Runtime, TypeRefBuilder>; using super = remote::MetadataReader<Runtime, TypeRefBuilder>;
using super::readMetadata; using super::readMetadata;
using super::readObjCClassName; using super::readObjCClassName;
using super::readResolvedPointerValue;
std::unordered_map<typename super::StoredPointer, const TypeInfo *> Cache; std::unordered_map<typename super::StoredPointer, const TypeInfo *> Cache;
/// All buffers we need to keep around long term. This will automatically free them /// All buffers we need to keep around long term. This will automatically free them
@@ -789,6 +789,52 @@ public:
} }
} }
llvm::Optional<std::pair<const TypeRef *, RemoteAddress>>
getDynamicTypeAndAddressClassExistential(RemoteAddress ExistentialAddress) {
auto PointerValue =
readResolvedPointerValue(ExistentialAddress.getAddressData());
if (!PointerValue)
return {};
auto Result = readMetadataFromInstance(*PointerValue);
if (!Result)
return {};
auto TypeResult = readTypeFromMetadata(Result.getValue());
if (!TypeResult)
return {};
return {{std::move(TypeResult), RemoteAddress(*PointerValue)}};
}
llvm::Optional<std::pair<const TypeRef *, RemoteAddress>>
getDynamicTypeAndAddressErrorExistential(RemoteAddress ExistentialAddress,
bool *IsBridgedError = nullptr) {
auto Result = readMetadataAndValueErrorExistential(ExistentialAddress);
if (!Result)
return {};
auto TypeResult =
readTypeFromMetadata(Result->MetadataAddress.getAddressData());
if (!TypeResult)
return {};
if (IsBridgedError)
*IsBridgedError = Result->IsBridgedError;
return {{TypeResult, Result->PayloadAddress}};
}
llvm::Optional<std::pair<const TypeRef *, RemoteAddress>>
getDynamicTypeAndAddressOpaqueExistential(RemoteAddress ExistentialAddress) {
auto Result = readMetadataAndValueOpaqueExistential(ExistentialAddress);
if (!Result)
return {};
auto TypeResult =
readTypeFromMetadata(Result->MetadataAddress.getAddressData());
if (!TypeResult)
return {};
return {{std::move(TypeResult), Result->PayloadAddress}};
}
bool projectExistential(RemoteAddress ExistentialAddress, bool projectExistential(RemoteAddress ExistentialAddress,
const TypeRef *ExistentialTR, const TypeRef *ExistentialTR,
const TypeRef **OutInstanceTR, const TypeRef **OutInstanceTR,
@@ -850,6 +896,75 @@ public:
return false; return false;
} }
} }
/// A version of `projectExistential` tailored for LLDB.
/// This version dereferences the resulting TypeRef if it wraps
/// a class type, it also dereferences the input `ExistentialAddress` before
/// attempting to find its dynamic type and address when dealing with error
/// existentials.
llvm::Optional<std::pair<const TypeRef *, RemoteAddress>>
projectExistentialAndUnwrapClass(RemoteAddress ExistentialAddress,
const TypeRef &ExistentialTR) {
auto IsClass = [](const TypeRef *TypeResult) {
// When the existential wraps a class type, LLDB expects that the
// address returned is the class instance itself and not the address
// of the reference.
bool IsClass = TypeResult->getKind() == TypeRefKind::ForeignClass ||
TypeResult->getKind() == TypeRefKind::ObjCClass;
if (auto *nominal = llvm::dyn_cast<NominalTypeRef>(TypeResult))
IsClass = nominal->isClass();
else if (auto *boundGeneric =
llvm::dyn_cast<BoundGenericTypeRef>(TypeResult))
IsClass = boundGeneric->isClass();
return IsClass;
};
auto DereferenceAndSet = [&](RemoteAddress &Address) {
auto PointerValue = readResolvedPointerValue(Address.getAddressData());
if (!PointerValue)
return false;
Address = RemoteAddress(*PointerValue);
return true;
};
auto ExistentialRecordTI = getRecordTypeInfo(&ExistentialTR, nullptr);
if (!ExistentialRecordTI)
return {};
switch (ExistentialRecordTI->getRecordKind()) {
case RecordKind::ClassExistential:
return getDynamicTypeAndAddressClassExistential(ExistentialAddress);
case RecordKind::ErrorExistential: {
// LLDB stores the address of the error pointer.
if (!DereferenceAndSet(ExistentialAddress))
return {};
bool IsBridgedError = false;
auto Pair = getDynamicTypeAndAddressErrorExistential(ExistentialAddress,
&IsBridgedError);
if (!Pair)
return {};
if (!IsBridgedError && IsClass(std::get<const TypeRef *>(*Pair)))
if (!DereferenceAndSet(std::get<RemoteAddress>(*Pair)))
return {};
return Pair;
}
case RecordKind::OpaqueExistential: {
auto Pair = getDynamicTypeAndAddressOpaqueExistential(ExistentialAddress);
if (!Pair)
return {};
if (IsClass(std::get<const TypeRef *>(*Pair)))
if (!DereferenceAndSet(std::get<RemoteAddress>(*Pair)))
return {};
return Pair;
}
default:
return {};
}
}
/// Projects the value of an enum. /// Projects the value of an enum.
/// ///
@@ -889,6 +1004,12 @@ public:
} }
} }
const RecordTypeInfo *getRecordTypeInfo(const TypeRef *TR,
remote::TypeInfoProvider *ExternalTypeInfo) {
auto *TypeInfo = getTypeInfo(TR, ExternalTypeInfo);
return dyn_cast_or_null<const RecordTypeInfo>(TypeInfo);
}
/// Iterate the protocol conformance cache tree rooted at NodePtr, calling /// Iterate the protocol conformance cache tree rooted at NodePtr, calling
/// Call with the type and protocol in each node. /// Call with the type and protocol in each node.
void iterateConformanceTree(StoredPointer NodePtr, void iterateConformanceTree(StoredPointer NodePtr,

View File

@@ -247,6 +247,19 @@ int swift_reflection_projectExistential(SwiftReflectionContextRef ContextRef,
swift_typeref_t *OutInstanceTypeRef, swift_typeref_t *OutInstanceTypeRef,
swift_addr_t *OutStartOfInstanceData); swift_addr_t *OutStartOfInstanceData);
/// Like swift_reflection_projectExistential, with 2 differences:
///
/// - When dealing with an error existential, this version will dereference
/// the ExistentialAddress before proceeding.
/// - After setting OutInstanceTypeRef and OutStartOfInstanceData this version
/// may derefence and set OutStartOfInstanceData if OutInstanceTypeRef is a
/// class TypeRef.
SWIFT_REMOTE_MIRROR_LINKAGE
int swift_reflection_projectExistentialAndUnwrapClass(
SwiftReflectionContextRef ContextRef, swift_addr_t ExistentialAddress,
swift_typeref_t ExistentialTypeRef, swift_typeref_t *OutInstanceTypeRef,
swift_addr_t *OutStartOfInstanceData);
/// Projects the value of an enum. /// Projects the value of an enum.
/// ///
/// Takes the address and typeref for an enum and determines the /// Takes the address and typeref for an enum and determines the

View File

@@ -17,6 +17,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
let RequestInstanceKind = "k" let RequestInstanceKind = "k"
let RequestShouldUnwrapClassExistential = "u"
let RequestInstanceAddress = "i" let RequestInstanceAddress = "i"
let RequestReflectionInfos = "r" let RequestReflectionInfos = "r"
let RequestImages = "m" let RequestImages = "m"
@@ -346,11 +347,15 @@ internal func sendPointerSize() {
/// The parent sends a Done message to indicate that it's done /// The parent sends a Done message to indicate that it's done
/// looking at this instance. It will continue to ask for instances, /// looking at this instance. It will continue to ask for instances,
/// so call doneReflecting() when you don't have any more instances. /// so call doneReflecting() when you don't have any more instances.
internal func reflect(instanceAddress: UInt, kind: InstanceKind) { internal func reflect(instanceAddress: UInt,
kind: InstanceKind,
shouldUnwrapClassExistential: Bool = false) {
while let command = readLine(strippingNewline: true) { while let command = readLine(strippingNewline: true) {
switch command { switch command {
case String(validatingUTF8: RequestInstanceKind)!: case String(validatingUTF8: RequestInstanceKind)!:
sendValue(kind.rawValue) sendValue(kind.rawValue)
case String(validatingUTF8: RequestShouldUnwrapClassExistential)!:
sendValue(shouldUnwrapClassExistential)
case String(validatingUTF8: RequestInstanceAddress)!: case String(validatingUTF8: RequestInstanceAddress)!:
sendValue(instanceAddress) sendValue(instanceAddress)
case String(validatingUTF8: RequestReflectionInfos)!: case String(validatingUTF8: RequestReflectionInfos)!:
@@ -437,12 +442,18 @@ public func reflect(object: AnyObject) {
/// The test doesn't care about the witness tables - we only care /// The test doesn't care about the witness tables - we only care
/// about what's in the buffer, so we always put these values into /// about what's in the buffer, so we always put these values into
/// an Any existential. /// an Any existential.
public func reflect<T>(any: T, kind: InstanceKind = .Existential) { ///
/// If shouldUnwrapClassExistential is set to true, this exercises
/// projectExistentialAndUnwrapClass instead of projectExistential.
public func reflect<T>(any: T, kind: InstanceKind = .Existential,
shouldUnwrapClassExistential: Bool = false) {
let any: Any = any let any: Any = any
let anyPointer = UnsafeMutablePointer<Any>.allocate(capacity: MemoryLayout<Any>.size) let anyPointer = UnsafeMutablePointer<Any>.allocate(capacity: MemoryLayout<Any>.size)
anyPointer.initialize(to: any) anyPointer.initialize(to: any)
let anyPointerValue = UInt(bitPattern: anyPointer) let anyPointerValue = UInt(bitPattern: anyPointer)
reflect(instanceAddress: anyPointerValue, kind: kind) reflect(instanceAddress: anyPointerValue,
kind: kind,
shouldUnwrapClassExistential: shouldUnwrapClassExistential)
anyPointer.deallocate() anyPointer.deallocate()
} }
@@ -474,6 +485,21 @@ public func reflect<T: Error>(error: T) {
reflect(instanceAddress: errorPointerValue, kind: .ErrorExistential) reflect(instanceAddress: errorPointerValue, kind: .ErrorExistential)
} }
// Like reflect<T: Error>(error: T), but calls projectExistentialAndUnwrapClass
// instead of projectExistential and adds an extra level of indirection, which is
// what projectExistentialAndUnwrapClass expects.
public func reflectUnwrappingClassExistential<T: Error>(error: T) {
let error: Error = error
let errorPointerValue = unsafeBitCast(error, to: UInt.self)
let anyPointer = UnsafeMutablePointer<Any>.allocate(capacity: MemoryLayout<Any>.size)
anyPointer.initialize(to: errorPointerValue)
let anyPointerValue = UInt(bitPattern: anyPointer)
reflect(instanceAddress: anyPointerValue,
kind: .ErrorExistential,
shouldUnwrapClassExistential: true)
anyPointer.deallocate()
}
// Reflect an `Enum` // Reflect an `Enum`
// //
// These are handled like existentials, but // These are handled like existentials, but

View File

@@ -571,6 +571,23 @@ int swift_reflection_projectExistential(SwiftReflectionContextRef ContextRef,
return Success; return Success;
} }
int swift_reflection_projectExistentialAndUnwrapClass(SwiftReflectionContextRef ContextRef,
swift_addr_t ExistentialAddress,
swift_typeref_t ExistentialTypeRef,
swift_typeref_t *InstanceTypeRef,
swift_addr_t *StartOfInstanceData) {
auto Context = ContextRef->nativeContext;
auto ExistentialTR = reinterpret_cast<const TypeRef *>(ExistentialTypeRef);
auto RemoteExistentialAddress = RemoteAddress(ExistentialAddress);
auto Pair = Context->projectExistentialAndUnwrapClass(
RemoteExistentialAddress, *ExistentialTR);
if (!Pair.hasValue())
return false;
*InstanceTypeRef = reinterpret_cast<swift_typeref_t>(std::get<const TypeRef *>(*Pair));
*StartOfInstanceData = std::get<RemoteAddress>(*Pair).getAddressData();
return true;
}
int swift_reflection_projectEnumValue(SwiftReflectionContextRef ContextRef, int swift_reflection_projectEnumValue(SwiftReflectionContextRef ContextRef,
swift_addr_t EnumAddress, swift_addr_t EnumAddress,
swift_typeref_t EnumTypeRef, swift_typeref_t EnumTypeRef,
@@ -761,4 +778,4 @@ const char *swift_reflection_iterateAsyncTaskAllocations(
Call(AllocationPtr, Count, ConvertedChunks.data(), ContextPtr); Call(AllocationPtr, Count, ConvertedChunks.data(), ContextPtr);
}); });
return returnableCString(ContextRef, Error); return returnableCString(ContextRef, Error);
} }

View File

@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
static const char *REQUEST_INSTANCE_KIND = "k\n"; static const char *REQUEST_INSTANCE_KIND = "k\n";
static const char *REQUEST_SHOULD_UNWRAP_CLASS_EXISTENTIAL = "u\n";
static const char *REQUEST_INSTANCE_ADDRESS = "i\n"; static const char *REQUEST_INSTANCE_ADDRESS = "i\n";
static const char *REQUEST_REFLECTION_INFO = "r\n"; static const char *REQUEST_REFLECTION_INFO = "r\n";
static const char *REQUEST_IMAGES = "m\n"; static const char *REQUEST_IMAGES = "m\n";

View File

@@ -238,6 +238,17 @@ PipeMemoryReader_receiveInstanceKind(const PipeMemoryReader *Reader) {
return KindValue; return KindValue;
} }
static uint8_t PipeMemoryReader_receiveShouldUnwrapExistential(
const PipeMemoryReader *Reader) {
int WriteFD = PipeMemoryReader_getParentWriteFD(Reader);
write(WriteFD, REQUEST_SHOULD_UNWRAP_CLASS_EXISTENTIAL, 2);
uint8_t ShouldUnwrap = 0;
PipeMemoryReader_collectBytesFromPipe(Reader, &ShouldUnwrap,
sizeof(ShouldUnwrap));
DEBUG_LOG("Requested if should unwrap class existential is", KindValue);
return ShouldUnwrap;
}
static uintptr_t static uintptr_t
PipeMemoryReader_receiveInstanceAddress(const PipeMemoryReader *Reader) { PipeMemoryReader_receiveInstanceAddress(const PipeMemoryReader *Reader) {
int WriteFD = PipeMemoryReader_getParentWriteFD(Reader); int WriteFD = PipeMemoryReader_getParentWriteFD(Reader);
@@ -445,24 +456,25 @@ int reflectHeapObject(SwiftReflectionContextRef RC,
return 1; return 1;
} }
int reflectExistential(SwiftReflectionContextRef RC, int reflectExistentialImpl(
const PipeMemoryReader Pipe, SwiftReflectionContextRef RC, const PipeMemoryReader Pipe,
swift_typeref_t MockExistentialTR) { swift_typeref_t MockExistentialTR,
int (*ProjectExistentialFn)(SwiftReflectionContextRef, swift_addr_t,
swift_typeref_t, swift_typeref_t *,
swift_addr_t *)) {
uintptr_t instance = PipeMemoryReader_receiveInstanceAddress(&Pipe); uintptr_t instance = PipeMemoryReader_receiveInstanceAddress(&Pipe);
if (instance == 0) { if (instance == 0) {
// Child has no more instances to examine // Child has no more instances to examine
PipeMemoryReader_sendDoneMessage(&Pipe); PipeMemoryReader_sendDoneMessage(&Pipe);
return 0; return 0;
} }
printf("Instance pointer in child address space: 0x%lx\n", printf("Instance pointer in child address space: 0x%lx\n", instance);
instance);
swift_typeref_t InstanceTypeRef; swift_typeref_t InstanceTypeRef;
swift_addr_t StartOfInstanceData = 0; swift_addr_t StartOfInstanceData = 0;
if (!swift_reflection_projectExistential(RC, instance, MockExistentialTR, if (!ProjectExistentialFn(RC, instance, MockExistentialTR, &InstanceTypeRef,
&InstanceTypeRef, &StartOfInstanceData)) {
&StartOfInstanceData)) {
printf("swift_reflection_projectExistential failed.\n"); printf("swift_reflection_projectExistential failed.\n");
PipeMemoryReader_sendDoneMessage(&Pipe); PipeMemoryReader_sendDoneMessage(&Pipe);
return 0; return 0;
@@ -476,10 +488,28 @@ int reflectExistential(SwiftReflectionContextRef RC,
swift_reflection_dumpInfoForTypeRef(RC, InstanceTypeRef); swift_reflection_dumpInfoForTypeRef(RC, InstanceTypeRef);
printf("\n"); printf("\n");
printf("Start of instance data: 0x%" PRIx64 "\n", StartOfInstanceData);
printf("\n");
PipeMemoryReader_sendDoneMessage(&Pipe); PipeMemoryReader_sendDoneMessage(&Pipe);
return 1; return 1;
} }
int reflectExistential(SwiftReflectionContextRef RC,
const PipeMemoryReader Pipe,
swift_typeref_t MockExistentialTR) {
return reflectExistentialImpl(RC, Pipe, MockExistentialTR,
swift_reflection_projectExistential);
}
int reflectExistentialAndUnwrapClass(SwiftReflectionContextRef RC,
const PipeMemoryReader Pipe,
swift_typeref_t MockExistentialTR) {
return reflectExistentialImpl(
RC, Pipe, MockExistentialTR,
swift_reflection_projectExistentialAndUnwrapClass);
}
int reflectEnum(SwiftReflectionContextRef RC, int reflectEnum(SwiftReflectionContextRef RC,
const PipeMemoryReader Pipe) { const PipeMemoryReader Pipe) {
static const char Name[] = MANGLING_PREFIX_STR "ypD"; static const char Name[] = MANGLING_PREFIX_STR "ypD";
@@ -706,23 +736,38 @@ int doDumpHeapInstance(const char *BinaryFilename) {
break; break;
case Existential: { case Existential: {
static const char Name[] = MANGLING_PREFIX_STR "ypD"; static const char Name[] = MANGLING_PREFIX_STR "ypD";
swift_typeref_t AnyTR swift_typeref_t AnyTR = swift_reflection_typeRefForMangledTypeName(
= swift_reflection_typeRefForMangledTypeName(RC, RC, Name, sizeof(Name) - 1);
Name, sizeof(Name)-1); uint8_t ShouldUnwrap =
PipeMemoryReader_receiveShouldUnwrapExistential(&Pipe);
printf("Reflecting an existential.\n"); if (ShouldUnwrap) {
if (!reflectExistential(RC, Pipe, AnyTR)) printf("Reflecting an existential and unwrapping class.\n");
return EXIT_SUCCESS; if (!reflectExistentialAndUnwrapClass(RC, Pipe, AnyTR))
return EXIT_SUCCESS;
} else {
printf("Reflecting an existential.\n");
if (!reflectExistential(RC, Pipe, AnyTR))
return EXIT_SUCCESS;
}
break; break;
} }
case ErrorExistential: { case ErrorExistential: {
static const char ErrorName[] = MANGLING_PREFIX_STR "s5Error_pD"; static const char ErrorName[] = MANGLING_PREFIX_STR "s5Error_pD";
swift_typeref_t ErrorTR swift_typeref_t ErrorTR = swift_reflection_typeRefForMangledTypeName(
= swift_reflection_typeRefForMangledTypeName(RC, RC, ErrorName, sizeof(ErrorName) - 1);
ErrorName, sizeof(ErrorName)-1); uint8_t ShouldUnwrap =
printf("Reflecting an error existential.\n"); PipeMemoryReader_receiveShouldUnwrapExistential(&Pipe);
if (!reflectExistential(RC, Pipe, ErrorTR))
return EXIT_SUCCESS; if (ShouldUnwrap) {
printf("Reflecting an error existential and unwrapping class.\n");
if (!reflectExistentialAndUnwrapClass(RC, Pipe, ErrorTR))
return EXIT_SUCCESS;
} else {
printf("Reflecting an error existential.\n");
if (!reflectExistential(RC, Pipe, ErrorTR))
return EXIT_SUCCESS;
}
break; break;
} }
case Closure: case Closure:

View File

@@ -71,6 +71,8 @@ reflect(any: mc)
// CHECK-64: Mangled name: $s12existentials7MyClassCyS2iG // CHECK-64: Mangled name: $s12existentials7MyClassCyS2iG
// CHECK-64: Demangled name: existentials.MyClass<Swift.Int, Swift.Int> // CHECK-64: Demangled name: existentials.MyClass<Swift.Int, Swift.Int>
// CHECK-64: Start of instance data: [[ADDR:0x[0-9a-fA-F]+]]
// CHECK-32: Reflecting an existential. // CHECK-32: Reflecting an existential.
// CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}} // CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-32: Type reference: // CHECK-32: Type reference:
@@ -82,6 +84,40 @@ reflect(any: mc)
// CHECK-32: Mangled name: $s12existentials7MyClassCyS2iG // CHECK-32: Mangled name: $s12existentials7MyClassCyS2iG
// CHECK-32: Demangled name: existentials.MyClass<Swift.Int, Swift.Int> // CHECK-32: Demangled name: existentials.MyClass<Swift.Int, Swift.Int>
// CHECK-32: Start of instance data: [[ADDR:0x[0-9a-fA-F]+]]
// Reflect and unwrap class existential should print the exact same info,
// EXCEPT for the start of instance data address.
reflect(any: mc, shouldUnwrapClassExistential: true)
// CHECK-64: Reflecting an existential and unwrapping class.
// CHECK-64: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-64: Type reference:
// CHECK-64: (bound_generic_class existentials.MyClass
// CHECK-64-NEXT: (struct Swift.Int)
// CHECK-64-NEXT: (struct Swift.Int))
// CHECK-64: Type info:
// CHECK-64: (reference kind=strong refcounting=native)
// CHECK-64: Mangled name: $s12existentials7MyClassCyS2iG
// CHECK-64: Demangled name: existentials.MyClass<Swift.Int, Swift.Int>
// CHECK-64: Start of instance data:
// CHECK-64-NOT: ![[ADDR]]
// CHECK-32: Reflecting an existential and unwrapping class.
// CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-32: Type reference:
// CHECK-32: (bound_generic_class existentials.MyClass
// CHECK-32-NEXT: (struct Swift.Int)
// CHECK-32-NEXT: (struct Swift.Int))
// CHECK-32: Type info:
// CHECK-32: (reference kind=strong refcounting=native)
// CHECK-32: Mangled name: $s12existentials7MyClassCyS2iG
// CHECK-32: Demangled name: existentials.MyClass<Swift.Int, Swift.Int>
// CHECK-32: Start of instance data:
// CHECK-32-NOT: ![[ADDR]]
// This value fits in the 3-word buffer in the container. // This value fits in the 3-word buffer in the container.
var smallStruct = MyStruct(x: 1, y: 2, z: 3) var smallStruct = MyStruct(x: 1, y: 2, z: 3)
reflect(any: smallStruct) reflect(any: smallStruct)
@@ -111,6 +147,9 @@ reflect(any: smallStruct)
// CHECK-64-NEXT: Mangled name: $s12existentials8MyStructVyS3iG // CHECK-64-NEXT: Mangled name: $s12existentials8MyStructVyS3iG
// CHECK-64-NEXT: Demangled name: existentials.MyStruct<Swift.Int, Swift.Int, Swift.Int> // CHECK-64-NEXT: Demangled name: existentials.MyStruct<Swift.Int, Swift.Int, Swift.Int>
// CHECK-64: Start of instance data: [[ADDR:0x[0-9a-fA-F]+]]
// CHECK-32: Reflecting an existential. // CHECK-32: Reflecting an existential.
// CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}} // CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-32: Type reference: // CHECK-32: Type reference:
@@ -136,6 +175,66 @@ reflect(any: smallStruct)
// CHECK-32-NEXT: Mangled name: $s12existentials8MyStructVyS3iG // CHECK-32-NEXT: Mangled name: $s12existentials8MyStructVyS3iG
// CHECK-32-NEXT: Demangled name: existentials.MyStruct<Swift.Int, Swift.Int, Swift.Int> // CHECK-32-NEXT: Demangled name: existentials.MyStruct<Swift.Int, Swift.Int, Swift.Int>
// CHECK-32: Start of instance data: [[ADDR:0x[0-9a-fA-F]+]]
reflect(any: smallStruct, shouldUnwrapClassExistential: true)
// CHECK-64: Reflecting an existential and unwrapping class.
// CHECK-64: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-64: Type reference:
// CHECK-64: (bound_generic_struct existentials.MyStruct
// CHECK-64-NEXT: (struct Swift.Int)
// CHECK-64-NEXT: (struct Swift.Int)
// CHECK-64-NEXT: (struct Swift.Int))
// CHECK-64: Type info:
// CHECK-64: (struct size=24 alignment=8 stride=24 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-64-NEXT: (field name=x offset=0
// CHECK-64-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-64-NEXT: (field name=_value offset=0
// CHECK-64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1))))
// CHECK-64-NEXT: (field name=y offset=8
// CHECK-64-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-64-NEXT: (field name=_value offset=0
// CHECK-64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1))))
// CHECK-64-NEXT: (field name=z offset=16
// CHECK-64-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-64-NEXT: (field name=_value offset=0
// CHECK-64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1)))))
// CHECK-64-NEXT: Mangled name: $s12existentials8MyStructVyS3iG
// CHECK-64-NEXT: Demangled name: existentials.MyStruct<Swift.Int, Swift.Int, Swift.Int>
// CHECK-64: Start of instance data:
// CHECK-64-NOT: ![[ADDR]]
// CHECK-32: Reflecting an existential and unwrapping class.
// CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-32: Type reference:
// CHECK-32: (bound_generic_struct existentials.MyStruct
// CHECK-32-NEXT: (struct Swift.Int)
// CHECK-32-NEXT: (struct Swift.Int)
// CHECK-32-NEXT: (struct Swift.Int))
// CHECK-32: Type info:
// CHECK-32: (struct size=12 alignment=4 stride=12 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-32-NEXT: (field name=x offset=0
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1))))
// CHECK-32-NEXT: (field name=y offset=4
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1))))
// CHECK-32-NEXT: (field name=z offset=8
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1)))))
// CHECK-32-NEXT: Mangled name: $s12existentials8MyStructVyS3iG
// CHECK-32-NEXT: Demangled name: existentials.MyStruct<Swift.Int, Swift.Int, Swift.Int>
// CHECK-32: Start of instance data:
// CHECK-32-NOT: ![[ADDR]]
// This value will be copied into a heap buffer, with a // This value will be copied into a heap buffer, with a
// pointer to it in the existential. // pointer to it in the existential.
var largeStruct = MyStruct(x: (1,1,1), y: (2,2,2), z: (3,3,3)) var largeStruct = MyStruct(x: (1,1,1), y: (2,2,2), z: (3,3,3))
@@ -204,6 +303,9 @@ reflect(any: largeStruct)
// CHECK-64-NEXT: Mangled name: $s12existentials8MyStructVySi_S2itSi_S2itSi_S2itG // CHECK-64-NEXT: Mangled name: $s12existentials8MyStructVySi_S2itSi_S2itSi_S2itG
// CHECK-64-NEXT: Demangled name: existentials.MyStruct<(Swift.Int, Swift.Int, Swift.Int), (Swift.Int, Swift.Int, Swift.Int), (Swift.Int, Swift.Int, Swift.Int)> // CHECK-64-NEXT: Demangled name: existentials.MyStruct<(Swift.Int, Swift.Int, Swift.Int), (Swift.Int, Swift.Int, Swift.Int), (Swift.Int, Swift.Int, Swift.Int)>
// CHECK-64: Start of instance data: [[ADDR:0x[0-9a-fA-F]+]]
// CHECK-32: Reflecting an existential. // CHECK-32: Reflecting an existential.
// CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}} // CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-32: Type reference: // CHECK-32: Type reference:
@@ -267,6 +369,142 @@ reflect(any: largeStruct)
// CHECK-32-NEXT: Mangled name: $s12existentials8MyStructVySi_S2itSi_S2itSi_S2itG // CHECK-32-NEXT: Mangled name: $s12existentials8MyStructVySi_S2itSi_S2itSi_S2itG
// CHECK-32-NEXT: Demangled name: existentials.MyStruct<(Swift.Int, Swift.Int, Swift.Int), (Swift.Int, Swift.Int, Swift.Int), (Swift.Int, Swift.Int, Swift.Int)> // CHECK-32-NEXT: Demangled name: existentials.MyStruct<(Swift.Int, Swift.Int, Swift.Int), (Swift.Int, Swift.Int, Swift.Int), (Swift.Int, Swift.Int, Swift.Int)>
// CHECK-32: Start of instance data: [[ADDR:0x[0-9a-fA-F]+]]
reflect(any: largeStruct, shouldUnwrapClassExistential: true)
// CHECK-64: Reflecting an existential and unwrapping class.
// CHECK-64: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-64: Type reference:
// CHECK-64: (bound_generic_struct existentials.MyStruct
// CHECK-64-NEXT: (tuple
// CHECK-64-NEXT: (struct Swift.Int)
// CHECK-64-NEXT: (struct Swift.Int)
// CHECK-64-NEXT: (struct Swift.Int))
// CHECK-64-NEXT: (tuple
// CHECK-64-NEXT: (struct Swift.Int)
// CHECK-64-NEXT: (struct Swift.Int)
// CHECK-64-NEXT: (struct Swift.Int))
// CHECK-64-NEXT: (tuple
// CHECK-64-NEXT: (struct Swift.Int)
// CHECK-64-NEXT: (struct Swift.Int)
// CHECK-64-NEXT: (struct Swift.Int)))
// CHECK-64: Type info:
// CHECK-64-NEXT: (struct size=72 alignment=8 stride=72 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-64-NEXT: (field name=x offset=0
// CHECK-64-NEXT: (tuple size=24 alignment=8 stride=24 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-64-NEXT: (field offset=0
// CHECK-64-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-64-NEXT: (field name=_value offset=0
// CHECK-64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1))))
// CHECK-64-NEXT: (field offset=8
// CHECK-64-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-64-NEXT: (field name=_value offset=0
// CHECK-64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1))))
// CHECK-64-NEXT: (field offset=16
// CHECK-64-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-64-NEXT: (field name=_value offset=0
// CHECK-64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1))))))
// CHECK-64-NEXT: (field name=y offset=24
// CHECK-64-NEXT: (tuple size=24 alignment=8 stride=24 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-64-NEXT: (field offset=0
// CHECK-64-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-64-NEXT: (field name=_value offset=0
// CHECK-64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1))))
// CHECK-64-NEXT: (field offset=8
// CHECK-64-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-64-NEXT: (field name=_value offset=0
// CHECK-64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1))))
// CHECK-64-NEXT: (field offset=16
// CHECK-64-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-64-NEXT: (field name=_value offset=0
// CHECK-64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1))))))
// CHECK-64-NEXT: (field name=z offset=48
// CHECK-64-NEXT: (tuple size=24 alignment=8 stride=24 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-64-NEXT: (field offset=0
// CHECK-64-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-64-NEXT: (field name=_value offset=0
// CHECK-64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1))))
// CHECK-64-NEXT: (field offset=8
// CHECK-64-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-64-NEXT: (field name=_value offset=0
// CHECK-64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1))))
// CHECK-64-NEXT: (field offset=16
// CHECK-64-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-64-NEXT: (field name=_value offset=0
// CHECK-64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1)))))))
// CHECK-64-NEXT: Mangled name: $s12existentials8MyStructVySi_S2itSi_S2itSi_S2itG
// CHECK-64-NEXT: Demangled name: existentials.MyStruct<(Swift.Int, Swift.Int, Swift.Int), (Swift.Int, Swift.Int, Swift.Int), (Swift.Int, Swift.Int, Swift.Int)>
// CHECK-64: Start of instance data:
// CHECK-64-NOT: ![[ADDR]]
// CHECK-32: Reflecting an existential and unwrapping class.
// CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-32: Type reference:
// CHECK-32: (bound_generic_struct existentials.MyStruct
// CHECK-32-NEXT: (tuple
// CHECK-32-NEXT: (struct Swift.Int)
// CHECK-32-NEXT: (struct Swift.Int)
// CHECK-32-NEXT: (struct Swift.Int))
// CHECK-32-NEXT: (tuple
// CHECK-32-NEXT: (struct Swift.Int)
// CHECK-32-NEXT: (struct Swift.Int)
// CHECK-32-NEXT: (struct Swift.Int))
// CHECK-32-NEXT: (tuple
// CHECK-32-NEXT: (struct Swift.Int)
// CHECK-32-NEXT: (struct Swift.Int)
// CHECK-32-NEXT: (struct Swift.Int)))
// CHECK-32: Type info:
// CHECK-32: (struct size=36 alignment=4 stride=36 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-32-NEXT: (field name=x offset=0
// CHECK-32-NEXT: (tuple size=12 alignment=4 stride=12 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-32-NEXT: (field offset=0
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1))))
// CHECK-32-NEXT: (field offset=4
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1))))
// CHECK-32-NEXT: (field offset=8
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1))))))
// CHECK-32-NEXT: (field name=y offset=12
// CHECK-32-NEXT: (tuple size=12 alignment=4 stride=12 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-32-NEXT: (field offset=0
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1))))
// CHECK-32-NEXT: (field offset=4
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1))))
// CHECK-32-NEXT: (field offset=8
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1))))))
// CHECK-32-NEXT: (field name=z offset=24
// CHECK-32-NEXT: (tuple size=12 alignment=4 stride=12 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-32-NEXT: (field offset=0
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1))))
// CHECK-32-NEXT: (field offset=4
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1))))
// CHECK-32-NEXT: (field offset=8
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1)))))))
// CHECK-32-NEXT: Mangled name: $s12existentials8MyStructVySi_S2itSi_S2itSi_S2itG
// CHECK-32-NEXT: Demangled name: existentials.MyStruct<(Swift.Int, Swift.Int, Swift.Int), (Swift.Int, Swift.Int, Swift.Int), (Swift.Int, Swift.Int, Swift.Int)>
// CHECK-32: Start of instance data:
// CHECK-32-NOT: ![[ADDR]]
// Function type: // Function type:
reflect(any: {largeStruct}) reflect(any: {largeStruct})
// CHECK-64: Mangled name: $s12existentials8MyStructVySi_S2itSi_S2itSi_S2itGyc // CHECK-64: Mangled name: $s12existentials8MyStructVySi_S2itSi_S2itSi_S2itGyc
@@ -346,6 +584,8 @@ reflect(any: he)
// CHECK-64-NEXT: Mangled name: $s12existentials8HasErrorV // CHECK-64-NEXT: Mangled name: $s12existentials8HasErrorV
// CHECK-64-NEXT: Demangled name: existentials.HasError // CHECK-64-NEXT: Demangled name: existentials.HasError
// CHECK-64: Start of instance data: [[ADDR:0x[0-9a-fA-F]+]]
// CHECK-32: Reflecting an existential. // CHECK-32: Reflecting an existential.
// CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}} // CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-32: Type reference: // CHECK-32: Type reference:
@@ -382,7 +622,91 @@ reflect(any: he)
// CHECK-32-NEXT: Mangled name: $s12existentials8HasErrorV // CHECK-32-NEXT: Mangled name: $s12existentials8HasErrorV
// CHECK-32-NEXT: Demangled name: existentials.HasError // CHECK-32-NEXT: Demangled name: existentials.HasError
reflect(error: MyError()) // CHECK-32: Start of instance data: [[ADDR:0x[0-9a-fA-F]+]]
reflect(any: he, shouldUnwrapClassExistential: true)
// CHECK-64: Reflecting an existential and unwrapping class.
// CHECK-64: Instance pointer in child address space: 0x{{[0-9a-fA-F+]}}
// CHECK-64: Type reference:
// CHECK-64: (struct existentials.HasError)
// CHECK-64: Type info:
// CHECK-64: (struct size=144 alignment=8 stride=144
// CHECK-64-NEXT: (field name=singleError offset=0
// CHECK-64-NEXT: (error_existential size=8 alignment=8 stride=8 num_extra_inhabitants=[[#num_extra_inhabitants_64bit]] bitwise_takable=1
// CHECK-64-NEXT: (field name=error offset=0
// CHECK-64-NEXT: (reference kind=strong refcounting=unknown))))
// CHECK-64-NEXT: (field name=errorInComposition offset=8
// CHECK-64-NEXT: (opaque_existential size=48 alignment=8 stride=48 num_extra_inhabitants=[[#num_extra_inhabitants_64bit]] bitwise_takable=1
// CHECK-64-NEXT: (field name=metadata offset=24
// CHECK-64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=[[#num_extra_inhabitants_64bit]] bitwise_takable=1))
// CHECK-64-NEXT: (field name=wtable offset=32
// CHECK-64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=1 bitwise_takable=1))
// CHECK-64-NEXT: (field name=wtable offset=40
// CHECK-64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=1 bitwise_takable=1))))
// CHECK-64-NEXT: (field name=customError offset=56
// CHECK-64-NEXT: (opaque_existential size=40 alignment=8 stride=40 num_extra_inhabitants=[[#num_extra_inhabitants_64bit]] bitwise_takable=1
// CHECK-64-NEXT: (field name=metadata offset=24
// CHECK-64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=[[#num_extra_inhabitants_64bit]] bitwise_takable=1))
// CHECK-64-NEXT: (field name=wtable offset=32
// CHECK-64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=1 bitwise_takable=1))))
// CHECK-64-NEXT: (field name=customErrorInComposition offset=96
// CHECK-64-NEXT: (opaque_existential size=48 alignment=8 stride=48 num_extra_inhabitants=[[#num_extra_inhabitants_64bit]] bitwise_takable=1
// CHECK-64-NEXT: (field name=metadata offset=24
// CHECK-64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=[[#num_extra_inhabitants_64bit]] bitwise_takable=1))
// CHECK-64-NEXT: (field name=wtable offset=32
// CHECK-64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=1 bitwise_takable=1))
// CHECK-64-NEXT: (field name=wtable offset=40
// CHECK-64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=1 bitwise_takable=1)))))
// CHECK-64-NEXT: Mangled name: $s12existentials8HasErrorV
// CHECK-64-NEXT: Demangled name: existentials.HasError
// CHECK-64: Start of instance data:
// CHECK-64-NOT: ![[ADDR]]
// CHECK-32: Reflecting an existential and unwrapping class.
// CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-32: Type reference:
// CHECK-32: (struct existentials.HasError)
// CHECK-32: Type info:
// CHECK-32: (struct size=72 alignment=4 stride=72 num_extra_inhabitants=4096 bitwise_takable=1
// CHECK-32-NEXT: (field name=singleError offset=0
// CHECK-32-NEXT: (error_existential size=4 alignment=4 stride=4 num_extra_inhabitants=4096 bitwise_takable=1
// CHECK-32-NEXT: (field name=error offset=0
// CHECK-32-NEXT: (reference kind=strong refcounting=unknown))))
// CHECK-32-NEXT: (field name=errorInComposition offset=4
// CHECK-32-NEXT: (opaque_existential size=24 alignment=4 stride=24 num_extra_inhabitants=4096 bitwise_takable=1
// CHECK-32-NEXT: (field name=metadata offset=12
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=4096 bitwise_takable=1))
// CHECK-32-NEXT: (field name=wtable offset=16
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=1 bitwise_takable=1))
// CHECK-32-NEXT: (field name=wtable offset=20
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=1 bitwise_takable=1))))
// CHECK-32-NEXT: (field name=customError offset=28
// CHECK-32-NEXT: (opaque_existential size=20 alignment=4 stride=20 num_extra_inhabitants=4096 bitwise_takable=1
// CHECK-32-NEXT: (field name=metadata offset=12
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=4096 bitwise_takable=1))
// CHECK-32-NEXT: (field name=wtable offset=16
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=1 bitwise_takable=1))))
// CHECK-32-NEXT: (field name=customErrorInComposition offset=48
// CHECK-32-NEXT: (opaque_existential size=24 alignment=4 stride=24 num_extra_inhabitants=4096 bitwise_takable=1
// CHECK-32-NEXT: (field name=metadata offset=12
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=4096 bitwise_takable=1))
// CHECK-32-NEXT: (field name=wtable offset=16
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=1 bitwise_takable=1))
// CHECK-32-NEXT: (field name=wtable offset=20
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=1 bitwise_takable=1)))))
// CHECK-32-NEXT: Mangled name: $s12existentials8HasErrorV
// CHECK-32-NEXT: Demangled name: existentials.HasError
// CHECK-32: Start of instance data:
// CHECK-32-NOT: ![[ADDR]]
let error = MyError()
reflect(error: error)
// CHECK-64: Reflecting an error existential. // CHECK-64: Reflecting an error existential.
// CHECK-64: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}} // CHECK-64: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
@@ -398,6 +722,8 @@ reflect(error: MyError())
// CHECK-64-NEXT: Mangled name: $s12existentials7MyErrorV // CHECK-64-NEXT: Mangled name: $s12existentials7MyErrorV
// CHECK-64-NEXT: Demangled name: existentials.MyError // CHECK-64-NEXT: Demangled name: existentials.MyError
// CHECK-64: Start of instance data: [[ADDR:0x[0-9a-fA-F]+]]
// CHECK-32: Reflecting an error existential. // CHECK-32: Reflecting an error existential.
// CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}} // CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-32: Type reference: // CHECK-32: Type reference:
@@ -412,4 +738,41 @@ reflect(error: MyError())
// CHECK-32-NEXT: Mangled name: $s12existentials7MyErrorV // CHECK-32-NEXT: Mangled name: $s12existentials7MyErrorV
// CHECK-32-NEXT: Demangled name: existentials.MyError // CHECK-32-NEXT: Demangled name: existentials.MyError
// CHECK-32: Start of instance data: [[ADDR:0x[0-9a-fA-F]+]]
reflectUnwrappingClassExistential(error: error)
// CHECK-64: Reflecting an error existential and unwrapping class.
// CHECK-64: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-64: Type reference:
// CHECK-64: (struct existentials.MyError)
// CHECK-64: Type info:
// CHECK-64: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-64-NEXT: (field name=i offset=0
// CHECK-64-NEXT: (struct size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-64-NEXT: (field name=_value offset=0
// CHECK-64-NEXT: (builtin size=8 alignment=8 stride=8 num_extra_inhabitants=0 bitwise_takable=1)))))
// CHECK-64-NEXT: Mangled name: $s12existentials7MyErrorV
// CHECK-64-NEXT: Demangled name: existentials.MyError
// CHECK-64: Start of instance data:
// CHECK-64-NOT: ![[ADDR]]
// CHECK-32: Reflecting an error existential and unwrapping class.
// CHECK-32: Instance pointer in child address space: 0x{{[0-9a-fA-F]+}}
// CHECK-32: Type reference:
// CHECK-32: (struct existentials.MyError)
// CHECK-32: Type info:
// CHECK-32: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-32-NEXT: (field name=i offset=0
// CHECK-32-NEXT: (struct size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1
// CHECK-32-NEXT: (field name=_value offset=0
// CHECK-32-NEXT: (builtin size=4 alignment=4 stride=4 num_extra_inhabitants=0 bitwise_takable=1)))))
// CHECK-32-NEXT: Mangled name: $s12existentials7MyErrorV
// CHECK-32-NEXT: Demangled name: existentials.MyError
// CHECK-32: Start of instance data:
// CHECK-32-NOT: ![[ADDR]]
doneReflecting() doneReflecting()