Skip to content

Commit 3cbabfd

Browse files
Merge pull request #15208 from aschwaighofer/resilient_enum_case_tags
IRGen: Make resilient enum's tag indices resilient
2 parents e19fc5e + 338dfef commit 3cbabfd

33 files changed

+443
-291
lines changed

docs/ABI/Mangling.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ Globals
8888
global ::= type protocol-conformance 'Wl' // lazy protocol witness table accessor
8989
global ::= type 'WV' // value witness table
9090
global ::= entity 'Wv' DIRECTNESS // field offset
91+
global ::= entity 'WC' // resilient enum tag index
9192

9293
global ::= type 'Wy' // Outlined Copy Function Type
9394
global ::= type 'We' // Outlined Consume Function Type

include/swift/ABI/ValueWitness.def

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -180,23 +180,23 @@ FUNCTION_VALUE_WITNESS(initializeBufferWithTakeOfBuffer,
180180
MUTABLE_VALUE_TYPE,
181181
(MUTABLE_BUFFER_TYPE, MUTABLE_BUFFER_TYPE, TYPE_TYPE))
182182

183-
/// int (*getEnumTagSinglePayload)(const T* enum, UINT_TYPE emptyCases)
183+
/// unsigned (*getEnumTagSinglePayload)(const T* enum, UINT_TYPE emptyCases)
184184
/// Given an instance of valid single payload enum with a payload of this
185185
/// witness table's type (e.g Optional<ThisType>) , get the tag of the enum.
186186
FUNCTION_VALUE_WITNESS(getEnumTagSinglePayload,
187187
GetEnumTagSinglePayload,
188-
INT_TYPE,
188+
UINT_TYPE,
189189
(IMMUTABLE_VALUE_TYPE, UINT_TYPE, TYPE_TYPE))
190190

191-
/// void (*storeEnumTagSinglePayload)(T* enum, INT_TYPE whichCase,
191+
/// void (*storeEnumTagSinglePayload)(T* enum, UINT_TYPE whichCase,
192192
/// UINT_TYPE emptyCases)
193193
/// Given uninitialized memory for an instance of a single payload enum with a
194194
/// payload of this witness table's type (e.g Optional<ThisType>), store the
195195
/// tag.
196196
FUNCTION_VALUE_WITNESS(storeEnumTagSinglePayload,
197197
StoreEnumTagSinglePayload,
198198
VOID_TYPE,
199-
(MUTABLE_VALUE_TYPE, INT_TYPE, UINT_TYPE, TYPE_TYPE))
199+
(MUTABLE_VALUE_TYPE, UINT_TYPE, UINT_TYPE, TYPE_TYPE))
200200

201201
END_VALUE_WITNESS_RANGE(RequiredValueWitnessFunction,
202202
StoreEnumTagSinglePayload)
@@ -327,11 +327,11 @@ END_VALUE_WITNESS_RANGE(ExtraInhabitantValueWitness,
327327
// The following value witnesses are conditionally present if the witnessed
328328
// type is an enum.
329329

330-
/// int (*getEnumTag)(T *obj, M *self);
330+
/// unsigned (*getEnumTag)(T *obj, M *self);
331331
///
332332
/// Given a valid object of this enum type, extracts the tag value indicating
333333
/// which case of the enum is inhabited. Returned values are in the range
334-
/// [-ElementsWithPayload..ElementsWithNoPayload-1].
334+
/// [0..NumElements-1].
335335
FUNCTION_VALUE_WITNESS(getEnumTag,
336336
GetEnumTag,
337337
INT_TYPE,
@@ -348,14 +348,14 @@ FUNCTION_VALUE_WITNESS(destructiveProjectEnumData,
348348
VOID_TYPE,
349349
(MUTABLE_VALUE_TYPE, TYPE_TYPE))
350350

351-
/// void (*destructiveInjectEnumTag)(T *obj, int tag, M *self);
351+
/// void (*destructiveInjectEnumTag)(T *obj, unsigned tag, M *self);
352352
/// Given an enum case tag and a valid object of case's payload type,
353353
/// destructively inserts the tag into the payload. The given tag value
354354
/// must be in the range [-ElementsWithPayload..ElementsWithNoPayload-1].
355355
FUNCTION_VALUE_WITNESS(destructiveInjectEnumTag,
356356
DestructiveInjectEnumTag,
357357
VOID_TYPE,
358-
(MUTABLE_VALUE_TYPE, INT_TYPE, TYPE_TYPE))
358+
(MUTABLE_VALUE_TYPE, UINT_TYPE, TYPE_TYPE))
359359

360360
END_VALUE_WITNESS_RANGE(EnumValueWitness,
361361
DestructiveInjectEnumTag)

include/swift/Demangling/DemangleNodes.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ NODE(DynamicAttribute)
6262
NODE(DirectMethodReferenceAttribute)
6363
NODE(DynamicSelf)
6464
CONTEXT_NODE(Enum)
65+
NODE(EnumCase)
6566
NODE(ErrorType)
6667
NODE(EscapingAutoClosureType)
6768
NODE(NoEscapeFunctionType)

include/swift/IRGen/Linking.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ class LinkEntity {
116116
/// ConstructorDecl* inside a protocol or a class.
117117
DispatchThunkAllocator,
118118

119+
/// A resilient enum tag index. The pointer is a EnumElementDecl*.
120+
EnumCase,
121+
119122
/// A field offset. The pointer is a VarDecl*.
120123
FieldOffset,
121124

@@ -434,6 +437,12 @@ class LinkEntity {
434437
return entity;
435438
}
436439

440+
static LinkEntity forEnumCase(EnumElementDecl *decl) {
441+
LinkEntity entity;
442+
entity.setForDecl(Kind::EnumCase, decl);
443+
return entity;
444+
}
445+
437446
static LinkEntity forObjCClassRef(ClassDecl *decl) {
438447
LinkEntity entity;
439448
entity.setForDecl(Kind::ObjCClassRef, decl);

include/swift/Runtime/Enum.h

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,30 +64,29 @@ void swift_initEnumMetadataSinglePayload(EnumMetadata *enumType,
6464
/// \param payload - type metadata for the payload case of the enum.
6565
/// \param emptyCases - the number of empty cases in the enum.
6666
///
67-
/// \returns -1 if the payload case is inhabited. If an empty case is inhabited,
68-
/// returns a value greater than or equal to zero and less than
67+
/// \returns 0 if the payload case is inhabited. If an empty case is inhabited,
68+
/// returns a value greater than or equal to one and less than or equal
6969
/// emptyCases.
7070
SWIFT_RUNTIME_EXPORT
71-
int swift_getEnumCaseSinglePayload(const OpaqueValue *value,
72-
const Metadata *payload,
73-
unsigned emptyCases);
74-
71+
unsigned swift_getEnumCaseSinglePayload(const OpaqueValue *value,
72+
const Metadata *payload,
73+
unsigned emptyCases);
7574

7675
/// \brief Store the tag value for the given case into a single-payload enum,
7776
/// whose associated payload (if any) has already been initialized.
7877
///
7978
/// \param value - pointer to the enum value. If the case being initialized is
80-
/// the payload case (-1), then the payload should be
79+
/// the payload case (0), then the payload should be
8180
/// initialized.
8281
/// \param payload - type metadata for the payload case of the enum.
83-
/// \param whichCase - unique value identifying the case. -1 for the payload
84-
/// case, or a value greater than or equal to zero and less
85-
/// than emptyCases for an empty case.
82+
/// \param whichCase - unique value identifying the case. 0 for the payload
83+
/// case, or a value greater than or equal to one and less
84+
/// than or equal emptyCases for an empty case.
8685
/// \param emptyCases - the number of empty cases in the enum.
8786
SWIFT_RUNTIME_EXPORT
8887
void swift_storeEnumTagSinglePayload(OpaqueValue *value,
8988
const Metadata *payload,
90-
int whichCase,
89+
unsigned whichCase,
9190
unsigned emptyCases);
9291

9392
/// \brief Initialize the type metadata for a generic, multi-payload

include/swift/Runtime/Metadata.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -842,7 +842,7 @@ struct TargetMetadata {
842842
getValueWitnesses()->_asXIVWT()->storeExtraInhabitant(value, index, this);
843843
}
844844

845-
int vw_getEnumTag(const OpaqueValue *value) const {
845+
unsigned vw_getEnumTag(const OpaqueValue *value) const {
846846
return getValueWitnesses()->_asEVWT()->getEnumTag(const_cast<OpaqueValue*>(value), this);
847847
}
848848
void vw_destructiveProjectEnumData(OpaqueValue *value) const {

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -987,7 +987,7 @@ FUNCTION(GetEnumCaseMultiPayload,
987987
ATTRS(NoUnwind, ReadOnly))
988988

989989
// void swift_storeEnumTagSinglePayload(opaque_t *obj, Metadata *payload,
990-
// int case_index,
990+
// unsigned case_index,
991991
// unsigned num_empty_cases);
992992
FUNCTION(StoreEnumTagSinglePayload,
993993
swift_storeEnumTagSinglePayload,

lib/Demangling/Demangler.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2049,6 +2049,9 @@ NodePointer Demangler::demangleSpecAttributes(Node::Kind SpecKind,
20492049

20502050
NodePointer Demangler::demangleWitness() {
20512051
switch (nextChar()) {
2052+
case 'C':
2053+
return createWithChild(Node::Kind::EnumCase,
2054+
popNode(isEntity));
20522055
case 'V':
20532056
return createWithChild(Node::Kind::ValueWitnessTable,
20542057
popNode(Node::Kind::Type));

lib/Demangling/NodePrinter.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,7 @@ class NodePrinter {
333333
case Node::Kind::NoEscapeFunctionType:
334334
case Node::Kind::ExplicitClosure:
335335
case Node::Kind::Extension:
336+
case Node::Kind::EnumCase:
336337
case Node::Kind::FieldOffset:
337338
case Node::Kind::FullTypeMetadata:
338339
case Node::Kind::Function:
@@ -1397,6 +1398,12 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
13971398
print(entity, /*asContext*/ false);
13981399
return nullptr;
13991400
}
1401+
case Node::Kind::EnumCase: {
1402+
Printer << "enum case for ";
1403+
auto entity = Node->getChild(0);
1404+
print(entity, /*asContext*/ false);
1405+
return nullptr;
1406+
}
14001407
case Node::Kind::ReabstractionThunk:
14011408
case Node::Kind::ReabstractionThunkHelper: {
14021409
if (Options.ShortenThunk) {

lib/Demangling/OldRemangler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -811,6 +811,11 @@ void Remangler::mangleFieldOffset(Node *node) {
811811
mangleChildNodes(node); // directness, entity
812812
}
813813

814+
void Remangler::mangleEnumCase(Node *node) {
815+
Out << "WC";
816+
mangleSingleChildNode(node); // enum case
817+
}
818+
814819
void Remangler::mangleProtocolWitnessTable(Node *node) {
815820
Out << "WP";
816821
mangleSingleChildNode(node); // protocol conformance

lib/Demangling/Remangler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,11 @@ void Remangler::mangleFieldOffset(Node *node) {
884884
mangleChildNode(node, 0); // directness
885885
}
886886

887+
void Remangler::mangleEnumCase(Node *node) {
888+
mangleSingleChildNode(node); // enum case
889+
Buffer << "WC";
890+
}
891+
887892
void Remangler::mangleFullTypeMetadata(Node *node) {
888893
mangleSingleChildNode(node);
889894
Buffer << "Mf";

lib/IRGen/GenDecl.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1521,6 +1521,12 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
15211521
case Kind::CoroutineContinuationPrototype:
15221522
return SILLinkage::PublicExternal;
15231523

1524+
1525+
case Kind::EnumCase: {
1526+
auto *elementDecl = cast<EnumElementDecl>(getDecl());
1527+
return getSILLinkage(getDeclLinkage(elementDecl), forDefinition);
1528+
}
1529+
15241530
case Kind::FieldOffset: {
15251531
auto *varDecl = cast<VarDecl>(getDecl());
15261532

@@ -1644,6 +1650,9 @@ bool LinkEntity::isAvailableExternally(IRGenModule &IGM) const {
16441650
case Kind::ProtocolDescriptor:
16451651
return ::isAvailableExternally(IGM, getDecl());
16461652

1653+
case Kind::EnumCase:
1654+
return ::isAvailableExternally(IGM, getDecl());
1655+
16471656
case Kind::DirectProtocolWitnessTable:
16481657
case Kind::ProtocolConformanceDescriptor:
16491658
return ::isAvailableExternally(IGM, getProtocolConformance()->getDeclContext());
@@ -3571,6 +3580,13 @@ Address IRGenModule::getAddrOfFieldOffset(VarDecl *var,
35713580
forDefinition);
35723581
}
35733582

3583+
Address IRGenModule::getAddrOfEnumCase(EnumElementDecl *Case,
3584+
ForDefinition_t forDefinition) {
3585+
LinkEntity entity = LinkEntity::forEnumCase(Case);
3586+
return getAddrOfSimpleVariable(*this, GlobalVars, entity, Int32Ty,
3587+
getPointerAlignment(), forDefinition);
3588+
}
3589+
35743590
void IRGenModule::emitNestedTypeDecls(DeclRange members) {
35753591
for (Decl *member : members) {
35763592
switch (member->getKind()) {

0 commit comments

Comments
 (0)