mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Implement MultiPayloadEnum support for projectEnumValue (#30635)
This code rearchitects and simplifies the projectEnumValue support by introducing a new `TypeInfo` subclass for each kind of enum, including trivial, no-payload, single-payload, and three different classes for multi-payload enums: * "UnsupportedEnum" that we don't understand. This returns "don't know" answers for all requests in cases where the runtime lacks enough information to accurately handle a particular enum. * MP Enums that only use a separate tag value. This includes generic enums and other dynamic layouts, as well as enums whose payloads have no spare bits. * MP Enums that use spare bits, possibly in addition to a separate tag. This logic can only be used, of course, if we can in fact compute a spare bit mask that agrees with the compiler. The final challenge is to choose one of the above three handlings for every MPE. Currently, we do not have an accurate source of information for the spare bit mask, so we never choose the third option above. We use the second option for dynamic MPE layouts (including generics) and the first for everything else. TODO: Once we can arrange for the compiler to expose spare bit mask data, we'll be able to use that to drive more MPE cases.
This commit is contained in:
@@ -581,28 +581,26 @@ int reflectEnum(SwiftReflectionContextRef RC,
|
||||
PipeMemoryReader_sendDoneMessage(&Pipe);
|
||||
return 1; // <<< Test cases also verify failures, so this must "succeed"
|
||||
}
|
||||
|
||||
char *CaseName = NULL;
|
||||
swift_typeref_t PayloadTypeRef = 0;
|
||||
if (!swift_reflection_getEnumCaseTypeRef(RC, EnumTypeRef, CaseIndex, &CaseName, &PayloadTypeRef)) {
|
||||
printf("swift_reflection_getEnumCaseTypeRef failed.\n");
|
||||
if ((unsigned)CaseIndex > InstanceTypeInfo.NumFields) {
|
||||
printf("swift_reflection_projectEnumValue returned invalid case.\n\n");
|
||||
PipeMemoryReader_sendDoneMessage(&Pipe);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (PayloadTypeRef == 0) {
|
||||
swift_childinfo_t CaseInfo
|
||||
= swift_reflection_childOfTypeRef(RC, EnumTypeRef, CaseIndex);
|
||||
|
||||
if (CaseInfo.TR == 0) {
|
||||
// Enum case has no payload
|
||||
printf("(enum_value name=%s index=%llu)\n",
|
||||
CaseName, (unsigned long long)CaseIndex);
|
||||
CaseInfo.Name, (unsigned long long)CaseIndex);
|
||||
} else {
|
||||
printf("(enum_value name=%s index=%llu\n",
|
||||
CaseName, (unsigned long long)CaseIndex);
|
||||
swift_reflection_dumpTypeRef(PayloadTypeRef);
|
||||
CaseInfo.Name, (unsigned long long)CaseIndex);
|
||||
swift_reflection_dumpTypeRef(CaseInfo.TR);
|
||||
printf(")\n");
|
||||
}
|
||||
printf("\n");
|
||||
// FIXME: Is there a better idiom for handling the returned case name?
|
||||
free(CaseName);
|
||||
PipeMemoryReader_sendDoneMessage(&Pipe);
|
||||
return 1;
|
||||
}
|
||||
@@ -654,21 +652,16 @@ int reflectEnumValue(SwiftReflectionContextRef RC,
|
||||
PipeMemoryReader_sendDoneMessage(&Pipe);
|
||||
return 1; // <<< Test cases rely on detecting this, so must "succeed"
|
||||
}
|
||||
|
||||
char *CaseName = NULL;
|
||||
swift_typeref_t PayloadTypeRef = 0;
|
||||
if (!swift_reflection_getEnumCaseTypeRef(RC, EnumTypeRef, CaseIndex,
|
||||
&CaseName, &PayloadTypeRef)) {
|
||||
printf("swift_reflection_getEnumCaseTypeRef failed.\n");
|
||||
if ((unsigned)CaseIndex > EnumTypeInfo.NumFields) {
|
||||
printf("swift_reflection_projectEnumValue returned invalid case.\n\n");
|
||||
PipeMemoryReader_sendDoneMessage(&Pipe);
|
||||
return 0;
|
||||
}
|
||||
|
||||
printf(".%s", CaseName);
|
||||
// FIXME: Is there a better idiom for handling the returned case name?
|
||||
free(CaseName);
|
||||
|
||||
EnumTypeRef = PayloadTypeRef;
|
||||
swift_childinfo_t CaseInfo
|
||||
= swift_reflection_childOfTypeRef(RC, EnumTypeRef, CaseIndex);
|
||||
printf(".%s", CaseInfo.Name);
|
||||
EnumTypeRef = CaseInfo.TR;
|
||||
if (EnumTypeRef != 0) {
|
||||
printf("(");
|
||||
parens += 1;
|
||||
|
||||
Reference in New Issue
Block a user