Skip to content

Commit b11899d

Browse files
authored
[IRGen] Disable simple single payload enum in layout strings (#70529)
rdar://119792426 There are a few issues with wrong assumptions around extra inhabitants that cause tags to not be identified properly in some cases. Until a proper fix is identified, we emit tag functions instead.
1 parent de10d01 commit b11899d

File tree

6 files changed

+101
-25
lines changed

6 files changed

+101
-25
lines changed

lib/IRGen/GenEnum.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,12 @@ EnumImplStrategy::emitResilientTagIndices(IRGenModule &IGM) const {
282282
}
283283
}
284284

285+
llvm::Value *
286+
EnumImplStrategy::emitFixedGetEnumTag(IRGenFunction &IGF, SILType T, Address enumAddr) const {
287+
assert(TIK >= Fixed);
288+
return emitGetEnumTag(IGF, T, enumAddr);
289+
}
290+
285291
namespace {
286292
/// Implementation strategy for singleton enums, with zero or one cases.
287293
class SingletonEnumImplStrategy final : public EnumImplStrategy {
@@ -1908,13 +1914,32 @@ namespace {
19081914
llvm::ConstantInt::get(IGF.IGM.Int32Ty, ElementsWithNoPayload.size());
19091915

19101916
auto PayloadT = getPayloadType(IGF.IGM, T);
1917+
19111918
auto opaqueAddr = Address(
19121919
IGF.Builder.CreateBitCast(enumAddr.getAddress(), IGF.IGM.OpaquePtrTy),
19131920
IGF.IGM.OpaqueTy, enumAddr.getAlignment());
1921+
19141922
return emitGetEnumTagSinglePayloadCall(IGF, PayloadT, numEmptyCases,
19151923
opaqueAddr);
19161924
}
19171925

1926+
1927+
llvm::Value *emitFixedGetEnumTag(IRGenFunction &IGF, SILType T,
1928+
Address enumAddr) const override {
1929+
assert(TIK >= Fixed);
1930+
auto numEmptyCases =
1931+
llvm::ConstantInt::get(IGF.IGM.Int32Ty, ElementsWithNoPayload.size());
1932+
1933+
auto PayloadT = getPayloadType(IGF.IGM, T);
1934+
1935+
auto &fixedTI = getFixedPayloadTypeInfo();
1936+
auto addr = IGF.Builder.CreateBitCast(
1937+
enumAddr.getAddress(), fixedTI.getStorageType()->getPointerTo());
1938+
return fixedTI.getEnumTagSinglePayload(IGF, numEmptyCases,
1939+
fixedTI.getAddressForPointer(addr),
1940+
PayloadT, /*isOutlined*/ false);
1941+
}
1942+
19181943
/// The payload for a single-payload enum is always placed in front and
19191944
/// will never have interleaved tag bits, so we can just bitcast the enum
19201945
/// address to the payload type for either injection or projection of the

lib/IRGen/GenEnum.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,14 @@ class EnumImplStrategy {
256256
SILType T,
257257
Address enumAddr) const = 0;
258258

259+
/// Return the enum case tag for the given value. Payload cases come first,
260+
/// followed by non-payload cases. Used for the getEnumTag value witness.
261+
///
262+
/// Only ever called for fixed types.
263+
virtual llvm::Value *emitFixedGetEnumTag(IRGenFunction &IGF,
264+
SILType T,
265+
Address enumAddr) const;
266+
259267
/// Project the address of the data for a case. Does not check or modify
260268
/// the referenced enum value.
261269
/// Corresponds to the SIL 'init_enum_data_addr' instruction.

lib/IRGen/GenValueWitness.cpp

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -923,15 +923,15 @@ static llvm::Constant *getEnumTagFunction(IRGenModule &IGM,
923923
auto mask = payloadTI.getFixedExtraInhabitantMask(IGM);
924924
auto tzCount = mask.countTrailingZeros();
925925
auto shiftedMask = mask.lshr(tzCount);
926-
auto toCount = shiftedMask.countTrailingOnes();
927-
if (payloadTI.mayHaveExtraInhabitants(IGM) &&
928-
(mask.countPopulation() > 64 ||
929-
toCount != mask.countPopulation() ||
930-
(tzCount % toCount != 0))) {
926+
// auto toCount = shiftedMask.countTrailingOnes();
927+
// if (payloadTI.mayHaveExtraInhabitants(IGM) &&
928+
// (mask.popcount() > 64 ||
929+
// toCount != mask.popcount() ||
930+
// (tzCount % toCount != 0))) {
931931
return IGM.getEnumFnGetEnumTagFn();
932-
} else {
933-
return IGM.getEnumSimpleGetEnumTagFn();
934-
}
932+
// } else {
933+
// return IGM.getEnumSimpleGetEnumTagFn();
934+
// }
935935
}
936936
}
937937

@@ -960,14 +960,14 @@ getDestructiveInjectEnumTagFunction(IRGenModule &IGM,
960960
auto mask = payloadTI.getFixedExtraInhabitantMask(IGM);
961961
auto tzCount = mask.countTrailingZeros();
962962
auto shiftedMask = mask.lshr(tzCount);
963-
auto toCount = shiftedMask.countTrailingOnes();
964-
if (payloadTI.mayHaveExtraInhabitants(IGM) &&
965-
(mask.countPopulation() > 64 || toCount != mask.countPopulation() ||
966-
(tzCount % toCount != 0))) {
963+
// auto toCount = shiftedMask.countTrailingOnes();
964+
// if (payloadTI.mayHaveExtraInhabitants(IGM) &&
965+
// (mask.popcount() > 64 || toCount != mask.popcount() ||
966+
// (tzCount % toCount != 0))) {
967967
return nullptr;
968-
} else {
969-
return IGM.getEnumSimpleDestructiveInjectEnumTagFn();
970-
}
968+
// } else {
969+
// return IGM.getEnumSimpleDestructiveInjectEnumTagFn();
970+
// }
971971
}
972972
}
973973

lib/IRGen/TypeLayout.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,7 @@ llvm::Function *createFixedEnumLoadTag(IRGenModule &IGM,
520520
auto enumAddr = typeInfo->getAddressForPointer(castEnumPtr);
521521

522522
auto &strategy = getEnumImplStrategy(IGM, entry.ty);
523-
auto tag = strategy.emitGetEnumTag(IGF, entry.ty, enumAddr);
523+
auto tag = strategy.emitFixedGetEnumTag(IGF, entry.ty, enumAddr);
524524
IGF.Builder.CreateRet(tag);
525525
});
526526

@@ -2233,7 +2233,7 @@ bool EnumTypeLayoutEntry::buildSinglePayloadRefCountString(
22332233
uint64_t zeroTagValue = 0;
22342234
unsigned xiBitCount = 0;
22352235
unsigned xiBitOffset = 0;
2236-
bool isSimple = true;
2236+
bool isSimple = false;
22372237

22382238
auto &payloadTI = **cases[0]->getFixedTypeInfo();
22392239

@@ -2248,17 +2248,17 @@ bool EnumTypeLayoutEntry::buildSinglePayloadRefCountString(
22482248

22492249
auto tzCount = mask.countTrailingZeros();
22502250
auto shiftedMask = mask.lshr(tzCount);
2251-
auto toCount = shiftedMask.countTrailingOnes();
2252-
if (mask.countPopulation() > 64 || toCount != mask.countPopulation() ||
2253-
(tzCount % toCount != 0)) {
2251+
// auto toCount = shiftedMask.countTrailingOnes();
2252+
// if (mask.popcount() > 64 || toCount != mask.popcount() ||
2253+
// (tzCount % toCount != 0)) {
22542254
// We currently don't handle cases with non-contiguous or > 64 bits of
22552255
// extra inhabitants
22562256
isSimple = false;
2257-
} else {
2258-
xiBitCount = std::min(64u, mask.countPopulation());
2259-
xiBitOffset = mask.countTrailingZeros();
2260-
zeroTagValue = lowValue.extractBitsAsZExtValue(xiBitCount, xiBitOffset);
2261-
}
2257+
// } else {
2258+
// xiBitCount = std::min(64u, mask.popcount());
2259+
// xiBitOffset = mask.countTrailingZeros();
2260+
// zeroTagValue = lowValue.extractBitsAsZExtValue(xiBitCount, xiBitOffset);
2261+
// }
22622262
}
22632263
}
22642264

test/Interpreter/Inputs/layout_string_witnesses_types_resilient.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,25 @@ public enum ResilientSinglePayloadEnumSimple {
5656
case nonEmpty(AnyObject)
5757
}
5858

59+
public enum MyString {
60+
case immortal(UInt64)
61+
case s(AnyObject)
62+
case t(AnyObject)
63+
}
64+
65+
public enum ResilientSinglePayloadEnumSimpleMultiExtraTagPayload {
66+
case empty0
67+
case empty1
68+
case empty2
69+
case empty3
70+
case empty4
71+
case empty5
72+
case empty6
73+
case empty7
74+
case empty8
75+
case nonEmpty(MyString)
76+
}
77+
5978
public enum ResilientSingletonEnum {
6079
case nonEmpty(AnyObject)
6180
}
@@ -92,6 +111,10 @@ public func getResilientSingletonEnumNonEmpty(_ x: AnyObject) -> ResilientSingle
92111
return .nonEmpty(x)
93112
}
94113

114+
public func getResilientSinglePayloadEnumSimpleMultiExtraTagPayloadEmpty3() -> ResilientSinglePayloadEnumSimpleMultiExtraTagPayload {
115+
return .empty3
116+
}
117+
95118
public enum ResilientSinglePayloadEnum {
96119
case empty0
97120
case empty1

test/Interpreter/layout_string_witnesses_dynamic.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,26 @@ func testResilientSinglePayloadEnumSimpleTag() {
842842

843843
testResilientSinglePayloadEnumSimpleTag()
844844

845+
func testResilientSinglePayloadEnumSimpleTagMultiExtraTagPayload() {
846+
let x = switch getResilientSinglePayloadEnumSimpleMultiExtraTagPayloadEmpty3() {
847+
case .nonEmpty: 0
848+
case .empty0: 1
849+
case .empty1: 2
850+
case .empty2: 3
851+
case .empty3: 4
852+
case .empty4: 5
853+
case .empty5: 6
854+
case .empty6: 7
855+
case .empty7: 8
856+
case .empty8: 9
857+
}
858+
859+
// CHECK: Enum case: 4
860+
print("Enum case: \(x)")
861+
}
862+
863+
testResilientSinglePayloadEnumSimpleTagMultiExtraTagPayload()
864+
845865
func testResilientSinglePayloadEnumIndirectTag() {
846866
let x = switch getResilientSinglePayloadEnumIndirectNonEmpty(SimpleClass(x: 23)) {
847867
case .nonEmpty: 0

0 commit comments

Comments
 (0)