Skip to content

Commit ea54c3b

Browse files
committed
First sketch of indirect enum support
This is basically an attempt to expand the test harness to fully dump indirect enums using the existing RemoteMirror facilities.
1 parent 1d47f1a commit ea54c3b

File tree

2 files changed

+125
-22
lines changed

2 files changed

+125
-22
lines changed

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

+80-22
Original file line numberDiff line numberDiff line change
@@ -617,37 +617,91 @@ int reflectEnumValue(SwiftReflectionContextRef RC,
617617
int parens = 0;
618618
while (EnumTypeRef != 0) {
619619
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) {
620+
switch (EnumTypeInfo.Kind) {
621+
case SWIFT_NO_PAYLOAD_ENUM:
622+
case SWIFT_SINGLE_PAYLOAD_ENUM:
623+
case SWIFT_MULTI_PAYLOAD_ENUM:
624+
{
625+
int CaseIndex;
626+
if (!swift_reflection_projectEnumValue(RC, EnumInstance, EnumTypeRef, &CaseIndex)) {
627+
printf("swift_reflection_projectEnumValue failed.\n\n");
628+
PipeMemoryReader_sendDoneMessage(&Pipe);
629+
return 1; // <<< Test cases rely on detecting this, so must "succeed"
630+
}
631+
if ((unsigned)CaseIndex > EnumTypeInfo.NumFields) {
632+
printf("swift_reflection_projectEnumValue returned invalid case.\n\n");
633+
PipeMemoryReader_sendDoneMessage(&Pipe);
634+
return 0;
635+
}
636+
637+
swift_childinfo_t CaseInfo
638+
= swift_reflection_childOfTypeRef(RC, EnumTypeRef, CaseIndex);
639+
printf(".%s", CaseInfo.Name);
640+
EnumTypeRef = CaseInfo.TR;
641+
if (EnumTypeRef != 0) {
642+
printf("(");
643+
parens += 1;
644+
}
645+
break;
646+
}
647+
case SWIFT_STRONG_REFERENCE: // Might be an indirect enum...
648+
{
649+
// Get the pointer value from the target
650+
void *outFreeContext = NULL;
651+
const void *rawPtr = PipeMemoryReader_readBytes(&Pipe, EnumInstance, 8, &outFreeContext);
652+
uintptr_t instance = *(uintptr_t *)rawPtr;
653+
654+
swift_typeinfo_t TI = swift_reflection_infoForInstance(RC, instance);
655+
if (TI.Kind == SWIFT_CLOSURE_CONTEXT) {
656+
printf("********** FOUND Closure Context **************\n");
657+
swift_typeref_t TR = swift_reflection_typeRefForInstance(RC, instance);
658+
printf("Type reference for instance: ");
659+
swift_reflection_dumpTypeRef(TR);
660+
printf("\n");
661+
662+
swift_typeinfo_t TI1 = swift_reflection_infoForTypeRef(RC, TR);
663+
printf("Type info for type ref: Kind: %d NumFields: %d\n", TI1.Kind, TI1.NumFields);
664+
665+
swift_typeinfo_t TI = swift_reflection_infoForInstance(RC, instance);
666+
printf("Type info for instance: Kind: %d NumFields: %d\n", TI.Kind, TI.NumFields);
667+
668+
printf("Type info for instance:\n");
669+
swift_reflection_dumpInfoForInstance(RC, instance);
670+
printf("\n");
671+
672+
// XXX FIXME THIS BREAKS?! What is the right way to reflect a closure context?
673+
swift_childinfo_t CaseInfo
674+
= swift_reflection_childOfTypeRef(RC, TR, 0);
675+
676+
if (CaseInfo.TR != 0) {
677+
printf("******** Read Case 0 *************\n");
678+
swift_typeinfo_t maybeEnumTI = swift_reflection_infoForTypeRef(RC, CaseInfo.TR);
679+
if (maybeEnumTI.Kind == SWIFT_NO_PAYLOAD_ENUM
680+
|| maybeEnumTI.Kind == SWIFT_SINGLE_PAYLOAD_ENUM
681+
|| maybeEnumTI.Kind == SWIFT_MULTI_PAYLOAD_ENUM) {
682+
printf("******** FOUND INDIRECT ENUM *************\n");
683+
EnumTypeRef = 0; // REMOVE ME
684+
break;
685+
}
686+
} else {
687+
printf("!!!!!!!!! Case 0 has no TR\n");
688+
}
689+
} else {
690+
printf("!!!!!!!!!! Not a closure context\n");
691+
}
692+
}
693+
default:
694+
{
695+
EnumTypeRef = 0;
623696
if (parens == 0) {
624697
printf(".??"); // Enum was optimized away, print "something"
625698
} else {
626699
printf("_");
627700
}
628701
break;
629702
}
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;
641703
}
642704

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;
650-
}
651705
}
652706
for (int i = 0; i < parens; ++i) {
653707
printf(")");
@@ -724,6 +778,10 @@ int doDumpHeapInstance(const char *BinaryFilename) {
724778
exit(status);
725779
}
726780
default: { // Parent
781+
for (int i = 5; i > 1; i--) {
782+
fprintf(stderr, "%d\n", i);
783+
sleep(1);
784+
}
727785
close(PipeMemoryReader_getChildReadFD(&Pipe));
728786
close(PipeMemoryReader_getChildWriteFD(&Pipe));
729787
SwiftReflectionContextRef RC =
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+

0 commit comments

Comments
 (0)