Skip to content

Commit 791d780

Browse files
authored
Merge pull request #59488 from tbkka/tbkka-remoteMirrorIndirectEnums
Test support for indirect enums in RemoteMirror
2 parents ba3973b + 017373b commit 791d780

File tree

3 files changed

+113
-24
lines changed

3 files changed

+113
-24
lines changed

stdlib/tools/swift-reflection-test/swift-reflection-test.c

Lines changed: 67 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -615,38 +615,78 @@ int reflectEnumValue(SwiftReflectionContextRef RC,
615615

616616
printf("Value: ");
617617
int parens = 0;
618+
// Walk into successively nested enum types...
618619
while (EnumTypeRef != 0) {
619620
swift_typeinfo_t EnumTypeInfo = swift_reflection_infoForTypeRef(RC, EnumTypeRef);
620-
if (EnumTypeInfo.Kind != SWIFT_NO_PAYLOAD_ENUM
621-
&& EnumTypeInfo.Kind != SWIFT_SINGLE_PAYLOAD_ENUM
622-
&& EnumTypeInfo.Kind != SWIFT_MULTI_PAYLOAD_ENUM) {
621+
switch (EnumTypeInfo.Kind) {
622+
case SWIFT_NO_PAYLOAD_ENUM:
623+
case SWIFT_SINGLE_PAYLOAD_ENUM:
624+
case SWIFT_MULTI_PAYLOAD_ENUM:
625+
{
626+
int CaseIndex;
627+
if (!swift_reflection_projectEnumValue(RC, EnumInstance, EnumTypeRef, &CaseIndex)) {
628+
printf("swift_reflection_projectEnumValue failed.\n\n");
629+
PipeMemoryReader_sendDoneMessage(&Pipe);
630+
return 1; // <<< Test cases rely on detecting this, so must "succeed"
631+
}
632+
if ((unsigned)CaseIndex > EnumTypeInfo.NumFields) {
633+
printf("swift_reflection_projectEnumValue returned invalid case.\n\n");
634+
PipeMemoryReader_sendDoneMessage(&Pipe);
635+
return 0;
636+
}
637+
swift_childinfo_t CaseInfo
638+
= swift_reflection_childOfTypeRef(RC, EnumTypeRef, CaseIndex);
639+
printf(".%s", CaseInfo.Name);
640+
641+
if (EnumTypeInfo.Kind == SWIFT_NO_PAYLOAD_ENUM || CaseInfo.TR == 0) {
642+
// No payload here, so end the walk
643+
EnumTypeRef = 0;
644+
} else {
645+
// There's a payload!
646+
printf("(");
647+
parens += 1;
648+
EnumTypeRef = CaseInfo.TR; // Walk into payload to see if it's an enum
649+
650+
if (CaseInfo.Kind == SWIFT_STRONG_REFERENCE) { // Maybe an indirect enum?
651+
// Get the pointer value from the target
652+
void *outFreeContext = NULL;
653+
// !!! FIXME !!! obtain the pointer by properly projecting the enum value
654+
// Next lines are a hack to prove the concept.
655+
const void *rawPtr
656+
= PipeMemoryReader_readBytes((void *)&Pipe, EnumInstance, 8, &outFreeContext);
657+
uintptr_t instance = *(uintptr_t *)rawPtr & 0xffffffffffffff8ULL;
658+
PipeMemoryReader_freeBytes((void *)&Pipe, rawPtr, outFreeContext);
659+
660+
// Indirect enum stores the payload as the first field of a closure context
661+
swift_typeinfo_t TI = swift_reflection_infoForInstance(RC, instance);
662+
if (TI.Kind == SWIFT_CLOSURE_CONTEXT) {
663+
// Yep, it's an indirect enum. Let's follow the pointer...
664+
// TODO: Could we get here if we have an enum whose payload is a closure?
665+
swift_childinfo_t CaseInfo
666+
= swift_reflection_childOfInstance(RC, instance, 0);
667+
if (CaseInfo.Kind == SWIFT_NO_PAYLOAD_ENUM
668+
|| CaseInfo.Kind == SWIFT_SINGLE_PAYLOAD_ENUM
669+
|| CaseInfo.Kind == SWIFT_MULTI_PAYLOAD_ENUM) {
670+
// Found the indirect enum storage, loop to print it out.
671+
EnumTypeRef = CaseInfo.TR;
672+
EnumInstance = instance + CaseInfo.Offset;
673+
break;
674+
}
675+
}
676+
}
677+
}
678+
break;
679+
}
680+
default:
681+
{
682+
EnumTypeRef = 0;
623683
if (parens == 0) {
624684
printf(".??"); // Enum was optimized away, print "something"
625685
} else {
626686
printf("_");
627687
}
628688
break;
629689
}
630-
631-
int CaseIndex;
632-
if (!swift_reflection_projectEnumValue(RC, EnumInstance, EnumTypeRef, &CaseIndex)) {
633-
printf("swift_reflection_projectEnumValue failed.\n\n");
634-
PipeMemoryReader_sendDoneMessage(&Pipe);
635-
return 1; // <<< Test cases rely on detecting this, so must "succeed"
636-
}
637-
if ((unsigned)CaseIndex > EnumTypeInfo.NumFields) {
638-
printf("swift_reflection_projectEnumValue returned invalid case.\n\n");
639-
PipeMemoryReader_sendDoneMessage(&Pipe);
640-
return 0;
641-
}
642-
643-
swift_childinfo_t CaseInfo
644-
= swift_reflection_childOfTypeRef(RC, EnumTypeRef, CaseIndex);
645-
printf(".%s", CaseInfo.Name);
646-
EnumTypeRef = CaseInfo.TR;
647-
if (EnumTypeRef != 0) {
648-
printf("(");
649-
parens += 1;
650690
}
651691
}
652692
for (int i = 0; i < parens; ++i) {
@@ -724,6 +764,10 @@ int doDumpHeapInstance(const char *BinaryFilename) {
724764
exit(status);
725765
}
726766
default: { // Parent
767+
for (int i = 5; i > 1; i--) {
768+
fprintf(stderr, "%d\n", i);
769+
sleep(1);
770+
}
727771
close(PipeMemoryReader_getChildReadFD(&Pipe));
728772
close(PipeMemoryReader_getChildWriteFD(&Pipe));
729773
SwiftReflectionContextRef RC =
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -lswiftSwiftReflectionTest %s -o %t/reflect_Enum_MultiPayload_value
3+
// RUN: %target-codesign %t/reflect_Enum_MultiPayload_value
4+
5+
// RUN: %target-run %target-swift-reflection-test %t/reflect_Enum_MultiPayload_value | tee /dev/stderr | %FileCheck %s --check-prefix=CHECK --check-prefix=X%target-ptrsize --dump-input=fail
6+
7+
// REQUIRES: reflection_test_support
8+
// REQUIRES: objc_interop
9+
// REQUIRES: executable_test
10+
// UNSUPPORTED: use_os_stdlib
11+
12+
import SwiftReflectionTest
13+
14+
15+
indirect enum MPEWithInts {
16+
case stampA
17+
case envelopeA(Int64)
18+
case stampB
19+
case envelopeB(Double)
20+
case stampC
21+
case envelopeC((Int32, Int32))
22+
case stampD
23+
case stampE
24+
}
25+
26+
indirect enum SPEWithMPEPayload {
27+
case payloadA(MPEWithInts)
28+
case alsoA
29+
case alsoB
30+
case alsoC
31+
case alsoD
32+
}
33+
34+
35+
reflect(enumValue: SPEWithMPEPayload.payloadA(.stampB))
36+
37+
// CHECK: Reflecting an enum value.
38+
// CHECK-NEXT: Type reference:
39+
// CHECK-NEXT: (enum reflect_Enum_MultiPayload_value.SPEWithMPEPayload)
40+
// CHECK-NEXT: Value: .payloadA(.stampB)
41+
42+
doneReflecting()
43+
44+
// CHECK: Done.
45+

validation-test/Reflection/reflect_Enum_value.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -369,7 +369,7 @@ reflect(enumValue: OneIndirectPayload.child(.leafF))
369369
// CHECK: Reflecting an enum value.
370370
// CHECK-NEXT: Type reference:
371371
// CHECK-NEXT: (enum reflect_Enum_value.OneIndirectPayload)
372-
// CHECK-NEXT: Value: .child(_)
372+
// CHECK-NEXT: Value: .child(.leafF)
373373

374374
reflect(enumValue: OneIndirectPayload.leafF)
375375

0 commit comments

Comments
 (0)