Skip to content

Commit 9d8c381

Browse files
committed
Remove resilient tag indices
1 parent 02b8a06 commit 9d8c381

File tree

18 files changed

+208
-267
lines changed

18 files changed

+208
-267
lines changed

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/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/IRGen/GenEnum.cpp

Lines changed: 31 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -235,15 +235,10 @@ irgen::EnumImplStrategy::getTagIndex(EnumElementDecl *Case) const {
235235
llvm_unreachable("couldn't find case");
236236
}
237237

238-
int
239-
irgen::EnumImplStrategy::getResilientTagIndex(EnumElementDecl *Case) const {
240-
return getTagIndex(Case) - ElementsWithPayload.size();
241-
}
242-
243238
static void emitResilientTagIndex(IRGenModule &IGM,
244239
const EnumImplStrategy *strategy,
245240
EnumElementDecl *Case) {
246-
auto resilientIdx = strategy->getResilientTagIndex(Case);
241+
auto resilientIdx = strategy->getTagIndex(Case);
247242
auto global = IGM.getAddrOfEnumCase(Case, ForDefinition);
248243
cast<llvm::GlobalVariable>(global.getAddress())
249244
->setInitializer(llvm::ConstantInt::get(IGM.Int32Ty, resilientIdx));
@@ -312,11 +307,7 @@ namespace {
312307
llvm::Value *
313308
emitGetEnumTag(IRGenFunction &IGF, SILType T, Address enumAddr)
314309
const override {
315-
// Convert fragile tag index into resilient tag index.
316-
// - -1 -- if we have a payload
317-
// - 0 -- if there's no payload
318-
return llvm::ConstantInt::get(IGF.IGM.Int32Ty,
319-
!ElementsWithPayload.empty() ? -1 : 0);
310+
return llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0);
320311
}
321312

322313
llvm::Value *
@@ -755,10 +746,7 @@ namespace {
755746
Explosion value;
756747
loadAsTake(IGF, enumAddr, value);
757748

758-
// Converting fragile tag index into resilient tag index is
759-
// not necessary; there are no payload tags.
760-
return IGF.Builder.CreateZExtOrTrunc(value.claimNext(),
761-
IGF.IGM.Int32Ty);
749+
return IGF.Builder.CreateZExtOrTrunc(value.claimNext(), IGF.IGM.Int32Ty);
762750
}
763751

764752
llvm::Value *emitValueCaseTest(IRGenFunction &IGF,
@@ -1668,8 +1656,7 @@ namespace {
16681656
}
16691657

16701658
/// Emit a call into the runtime to get the current enum payload tag.
1671-
/// This returns a tag index in the range
1672-
/// [-ElementsWithPayload..ElementsWithNoPayload-1].
1659+
/// This returns a tag index in the range [0..NumElements-1].
16731660
llvm::Value *emitGetEnumTag(IRGenFunction &IGF, SILType T,
16741661
Address enumAddr) const override {
16751662
auto numEmptyCases =
@@ -2033,8 +2020,7 @@ namespace {
20332020

20342021
auto emitCase = [&](Element elt) {
20352022
auto tagVal =
2036-
llvm::ConstantInt::get(IGF.IGM.Int32Ty,
2037-
getResilientTagIndex(elt.decl));
2023+
llvm::ConstantInt::get(IGF.IGM.Int32Ty, getTagIndex(elt.decl));
20382024
auto found = destMap.find(elt.decl);
20392025
if (found != destMap.end())
20402026
swi->addCase(tagVal, found->second);
@@ -2100,7 +2086,8 @@ namespace {
21002086

21012087
// Non-payload cases use extra inhabitants, if any, or are discriminated
21022088
// by setting the tag bits.
2103-
unsigned tagIndex = getResilientTagIndex(elt);
2089+
// Use the index from ElementsWithNoPayload.
2090+
unsigned tagIndex = getTagIndex(elt) - 1;
21042091
unsigned numExtraInhabitants = getNumExtraInhabitantTagValues();
21052092
APInt payload;
21062093
unsigned extraTagValue;
@@ -2251,9 +2238,9 @@ namespace {
22512238
// Ask the runtime what case we have.
22522239
llvm::Value *which = emitGetEnumTag(IGF, T, addr);
22532240

2254-
// If it's -1 then we have the payload.
2255-
llvm::Value *hasPayload = IGF.Builder.CreateICmpEQ(which,
2256-
llvm::ConstantInt::getSigned(IGF.IGM.Int32Ty, -1));
2241+
// If it's 0 then we have the payload.
2242+
llvm::Value *hasPayload = IGF.Builder.CreateICmpEQ(
2243+
which, llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0));
22572244
IGF.Builder.CreateCondBr(hasPayload, payloadBB, noPayloadBB);
22582245

22592246
IGF.Builder.emitBlock(payloadBB);
@@ -2508,7 +2495,7 @@ namespace {
25082495

25092496
auto PayloadT = getPayloadType(IGF.IGM, T);
25102497
auto Addr = Address(opaqueAddr, dest.getAlignment());
2511-
auto *whichCase = llvm::ConstantInt::getSigned(IGF.IGM.Int32Ty, -1);
2498+
auto *whichCase = llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0);
25122499
auto *numEmptyCases =
25132500
llvm::ConstantInt::get(IGF.IGM.Int32Ty, ElementsWithNoPayload.size());
25142501
emitStoreEnumTagSinglePayloadCall(IGF, PayloadT, whichCase, numEmptyCases,
@@ -2778,14 +2765,14 @@ namespace {
27782765
// If the enum isn't fixed-layout, get the runtime to do this for us.
27792766
llvm::Value *caseIndex;
27802767
if (Case == getPayloadElement()) {
2781-
caseIndex = llvm::ConstantInt::getSigned(IGF.IGM.Int32Ty, -1);
2768+
caseIndex = llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0);
27822769
} else {
27832770
auto found = std::find_if(ElementsWithNoPayload.begin(),
27842771
ElementsWithNoPayload.end(),
27852772
[&](Element a) { return a.decl == Case; });
27862773
assert(found != ElementsWithNoPayload.end() &&
27872774
"case not in enum?!");
2788-
unsigned caseIndexVal = found - ElementsWithNoPayload.begin();
2775+
unsigned caseIndexVal = found - ElementsWithNoPayload.begin() + 1;
27892776
caseIndex = llvm::ConstantInt::get(IGF.IGM.Int32Ty, caseIndexVal);
27902777
}
27912778

@@ -2824,7 +2811,7 @@ namespace {
28242811
}
28252812

28262813
/// Constructs an enum value using a tag index in the range
2827-
/// [-ElementsWithPayload..ElementsWithNoPayload-1].
2814+
/// [0..NumElements-1].
28282815
void emitStoreTag(IRGenFunction &IGF, SILType T, Address enumAddr,
28292816
llvm::Value *tag) const override {
28302817
auto PayloadT = getPayloadType(IGF.IGM, T);
@@ -3410,8 +3397,7 @@ namespace {
34103397

34113398
public:
34123399

3413-
/// Returns a tag index in the range
3414-
/// [-ElementsWithPayload..ElementsWithNoPayload+1].
3400+
/// Returns a tag index in the range [0..NumElements-1].
34153401
llvm::Value *
34163402
emitGetEnumTag(IRGenFunction &IGF, SILType T, Address addr)
34173403
const override {
@@ -3421,10 +3407,7 @@ namespace {
34213407

34223408
if (TIK < Fixed) {
34233409
// Ask the runtime to extract the dynamically-placed tag.
3424-
llvm::Value *tagValue = loadDynamicTag(IGF, addr, T);
3425-
3426-
// Convert fragile tag index into resilient tag index.
3427-
return IGF.Builder.CreateSub(tagValue, payloadCases);
3410+
return loadDynamicTag(IGF, addr, T);
34283411
}
34293412

34303413
// For fixed-size enums, the currently inhabited case is a function of
@@ -3442,15 +3425,6 @@ namespace {
34423425
llvm::Value *tagValue = extractPayloadTag(IGF, payload, extraTagBits);
34433426
tagValue = IGF.Builder.CreateZExtOrTrunc(tagValue, IGF.IGM.Int32Ty);
34443427

3445-
// Subtract number of payload cases from the payload tag.
3446-
//
3447-
// If we have a payload case, this yields a negative value, which is the
3448-
// final resilient tag index.
3449-
//
3450-
// If we have a no-payload case, this yields a non-negative value, which
3451-
// is the most significant bits of the current case index.
3452-
tagValue = IGF.Builder.CreateSub(tagValue, payloadCases);
3453-
34543428
// If we don't have any no-payload cases, we are done -- the payload tag
34553429
// alone is enough to distinguish between all cases.
34563430
if (ElementsWithNoPayload.empty())
@@ -3480,21 +3454,27 @@ namespace {
34803454
// The no-payload cases are distributed between multiple payload tags;
34813455
// combine the payload tag with the payload value.
34823456

3457+
// First, subtract number of payload cases from the payload tag to get
3458+
// the most significant bits of the current case.
3459+
currentCase = IGF.Builder.CreateSub(tagValue, payloadCases);
3460+
34833461
// Shift the most significant bits of the tag value into place.
34843462
llvm::Constant *numCaseBitsVal =
34853463
llvm::ConstantInt::get(IGF.IGM.Int32Ty, numCaseBits);
3486-
currentCase = IGF.Builder.CreateShl(tagValue, numCaseBitsVal);
3464+
currentCase = IGF.Builder.CreateShl(currentCase, numCaseBitsVal);
34873465

34883466
// Add the payload value to the shifted payload tag.
34893467
//
34903468
// The result is a tag index in the range [0..ElementsWithNoPayload],
34913469
// so we are done.
34923470
currentCase = IGF.Builder.CreateOr(currentCase, payloadValue);
34933471
}
3472+
// Now, we have the index of a no-payload case. Add the number of payload
3473+
// cases back, to get an index of a case.
3474+
currentCase = IGF.Builder.CreateAdd(currentCase, payloadCases);
34943475

34953476
// Test if this is a payload or no-payload case.
3496-
llvm::Value *match = IGF.Builder.CreateICmpSGE(tagValue,
3497-
llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0));
3477+
llvm::Value *match = IGF.Builder.CreateICmpUGE(tagValue, payloadCases);
34983478

34993479
// Return one of the two values we computed based on the above.
35003480
return IGF.Builder.CreateSelect(match, currentCase, tagValue);
@@ -3734,8 +3714,7 @@ namespace {
37343714

37353715
auto emitCase = [&](Element elt) {
37363716
auto tagVal =
3737-
llvm::ConstantInt::get(IGF.IGM.Int32Ty,
3738-
getTagIndex(elt.decl));
3717+
llvm::ConstantInt::get(IGF.IGM.Int32Ty, getTagIndex(elt.decl));
37393718
auto found = destMap.find(elt.decl);
37403719
if (found != destMap.end())
37413720
tagSwitch->addCase(tagVal, found->second);
@@ -4666,17 +4645,11 @@ namespace {
46664645

46674646
// Use the runtime to initialize dynamic cases.
46684647
if (TIK < Fixed) {
4669-
// Convert resilient tag index into fragile tag index.
4670-
tag = IGF.Builder.CreateAdd(tag, numPayloadCases);
4671-
46724648
return storeDynamicTag(IGF, enumAddr, tag, T);
46734649
}
46744650

46754651
// If there are no empty cases, don't need a conditional.
46764652
if (ElementsWithNoPayload.empty()) {
4677-
// Convert resilient tag index into fragile tag index.
4678-
tag = IGF.Builder.CreateAdd(tag, numPayloadCases);
4679-
46804653
storePayloadTag(IGF, enumAddr, tag, T);
46814654
return;
46824655
}
@@ -4686,24 +4659,21 @@ namespace {
46864659
auto payloadBB = llvm::BasicBlock::Create(C);
46874660
auto endBB = llvm::BasicBlock::Create(C);
46884661

4689-
llvm::Value *cond = IGF.Builder.CreateICmpSGE(tag,
4690-
llvm::ConstantInt::get(IGF.IGM.Int32Ty, 0));
4662+
llvm::Value *cond = IGF.Builder.CreateICmpUGE(tag, numPayloadCases);
46914663
IGF.Builder.CreateCondBr(cond, noPayloadBB, payloadBB);
46924664

46934665
IGF.Builder.emitBlock(noPayloadBB);
46944666
{
46954667
ConditionalDominanceScope condition(IGF);
4696-
storeNoPayloadTag(IGF, enumAddr, tag, T);
4668+
storeNoPayloadTag(IGF, enumAddr,
4669+
IGF.Builder.CreateSub(tag, numPayloadCases), T);
46974670
IGF.Builder.CreateBr(endBB);
46984671
}
46994672

47004673
IGF.Builder.emitBlock(payloadBB);
47014674
{
47024675
ConditionalDominanceScope condition(IGF);
47034676

4704-
// Convert resilient tag index into fragile tag index.
4705-
tag = IGF.Builder.CreateAdd(tag, numPayloadCases);
4706-
47074677
storePayloadTag(IGF, enumAddr, tag, T);
47084678
IGF.Builder.CreateBr(endBB);
47094679
}
@@ -4883,11 +4853,6 @@ namespace {
48834853
std::move(WithNoPayload))
48844854
{ }
48854855

4886-
int getResilientTagIndex(EnumElementDecl *) const override {
4887-
// Resilient enum's should load the tag index from a global.
4888-
llvm_unreachable("Use loadResilientTagIndex instead");
4889-
}
4890-
48914856
llvm::Value *loadResilientTagIndex(IRGenFunction &IGF,
48924857
EnumElementDecl *Case) const {
48934858
auto address = IGF.IGM.getAddrOfEnumCase(Case, NotForDefinition);
@@ -5223,9 +5188,8 @@ EnumImplStrategy::get(TypeConverter &TC, SILType type, EnumDecl *theEnum) {
52235188

52245189
// Resilient enums are manipulated as opaque values, except we still
52255190
// make the following assumptions:
5226-
// 1) Physical case indices won't change
5227-
// 2) The indirect-ness of cases won't change
5228-
// 3) Payload types won't change in a non-resilient way
5191+
// 1) The indirect-ness of cases won't change
5192+
// 2) Payload types won't change in a non-resilient way
52295193
bool isResilient = TC.IGM.isResilient(theEnum, ResilienceExpansion::Maximal);
52305194

52315195
// The most general resilience scope where the enum type is visible.
@@ -5310,12 +5274,6 @@ EnumImplStrategy::get(TypeConverter &TC, SILType type, EnumDecl *theEnum) {
53105274
}
53115275
}
53125276

5313-
5314-
// Resilient tag numbering decreases for payload tags, so reverse the
5315-
// payload tags if this enum is resilient from any context.
5316-
if (TC.IGM.isResilient(theEnum, ResilienceExpansion::Minimal))
5317-
std::reverse(elementsWithPayload.begin(), elementsWithPayload.end());
5318-
53195277
assert(numElements == elementsWithPayload.size()
53205278
+ elementsWithNoPayload.size()
53215279
&& "not all elements accounted for");

0 commit comments

Comments
 (0)