Skip to content

Commit 6c2d883

Browse files
committed
Speculatively revert "IRGen: Make case numbering consistent for enums with empty payloads"
I suspect its breaking the build. I must've screwed up my testing. This reverts commit 86e6b81.
1 parent 4c6d972 commit 6c2d883

File tree

5 files changed

+35
-105
lines changed

5 files changed

+35
-105
lines changed

lib/IRGen/GenDecl.cpp

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2588,14 +2588,7 @@ StringRef IRGenModule::mangleType(CanType type, SmallVectorImpl<char> &buffer) {
25882588
return StringRef(buffer.data(), buffer.size());
25892589
}
25902590

2591-
/// Do we have to use resilient access patterns when working with this
2592-
/// declaration?
2593-
///
2594-
/// IRGen is primarily concerned with resilient handling of the following:
2595-
/// - For structs, a struct's size might change
2596-
/// - For enums, new cases can be added
2597-
/// - For classes, the superclass might change the size or number
2598-
/// of stored properties
2591+
/// Is the given declaration resilient?
25992592
bool IRGenModule::isResilient(Decl *D, ResilienceScope scope) {
26002593
auto NTD = dyn_cast<NominalTypeDecl>(D);
26012594
if (!NTD)
@@ -2611,23 +2604,6 @@ bool IRGenModule::isResilient(Decl *D, ResilienceScope scope) {
26112604
llvm_unreachable("Bad resilience scope");
26122605
}
26132606

2614-
// The most general resilience scope where the given declaration is visible.
2615-
ResilienceScope IRGenModule::getResilienceScopeForAccess(NominalTypeDecl *decl) {
2616-
if (decl->getModuleContext() == SILMod->getSwiftModule() &&
2617-
decl->getFormalAccess() != Accessibility::Public)
2618-
return ResilienceScope::Component;
2619-
return ResilienceScope::Universal;
2620-
}
2621-
2622-
// The most general resilience scope which has knowledge of the declaration's
2623-
// layout. Calling isResilient() with this scope will always return false.
2624-
ResilienceScope IRGenModule::getResilienceScopeForLayout(NominalTypeDecl *decl) {
2625-
if (isResilient(decl, ResilienceScope::Universal))
2626-
return ResilienceScope::Component;
2627-
2628-
return getResilienceScopeForAccess(decl);
2629-
}
2630-
26312607
/// Fetch the witness table access function for a protocol conformance.
26322608
llvm::Function *
26332609
IRGenModule::getAddrOfWitnessTableAccessFunction(

lib/IRGen/GenEnum.cpp

Lines changed: 32 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4598,22 +4598,17 @@ EnumImplStrategy *EnumImplStrategy::get(TypeConverter &TC,
45984598
std::vector<Element> elementsWithPayload;
45994599
std::vector<Element> elementsWithNoPayload;
46004600

4601-
// Resilient enums are manipulated as opaque values, except we still
4602-
// make the following assumptions:
4603-
// 1) Physical case indices won't change
4604-
// 2) The indirect-ness of cases won't change
4605-
// 3) Payload types won't change in a non-resilient way
4606-
bool isResilient = TC.IGM.isResilient(theEnum, ResilienceScope::Component);
4607-
4608-
// The most general resilience scope where the enum type is visible.
4609-
// Case numbering must not depend on any information that is not static
4610-
// in this resilience scope.
4611-
ResilienceScope accessScope = TC.IGM.getResilienceScopeForAccess(theEnum);
4612-
4613-
// The most general resilience scope where the enum's layout is known.
4614-
// Fixed-size optimizations can be applied if all payload types are
4615-
// fixed-size from this resilience scope.
4616-
ResilienceScope layoutScope = TC.IGM.getResilienceScopeForLayout(theEnum);
4601+
// The most general resilience scope that can have knowledge of this
4602+
// enum's layout. If all payload types have a fixed size in this
4603+
// resilience scope, we can make further assumptions to optimize
4604+
// layout.
4605+
ResilienceScope scope = ResilienceScope::Universal;
4606+
4607+
// TODO: Replace this with 'public or internal with @availability' check
4608+
// once that is in place
4609+
if (theEnum->getFormalAccess() != Accessibility::Public ||
4610+
TC.IGM.isResilient(theEnum, ResilienceScope::Universal))
4611+
scope = ResilienceScope::Component;
46174612

46184613
for (auto elt : theEnum->getAllElements()) {
46194614
numElements++;
@@ -4643,20 +4638,14 @@ EnumImplStrategy *EnumImplStrategy::get(TypeConverter &TC,
46434638
= TC.tryGetCompleteTypeInfo(origArgLoweredTy.getSwiftRValueType());
46444639
assert(origArgTI && "didn't complete type info?!");
46454640

4646-
// If the unsubstituted argument contains a generic parameter type, or
4647-
// is not fixed-size in all resilience domains that have knowledge of
4648-
// this enum's layout, we need to constrain our layout optimizations to
4649-
// what the runtime can reproduce.
4650-
if (!isResilient &&
4651-
!origArgTI->isFixedSize(layoutScope))
4641+
// If the unsubstituted argument contains a generic parameter type, or if
4642+
// the substituted argument is not universally fixed-size, we need to
4643+
// constrain our layout optimizations to what the runtime can reproduce.
4644+
if (!origArgTI->isFixedSize(scope))
46524645
alwaysFixedSize = IsNotFixedSize;
46534646

4654-
// If the payload is empty, turn the case into a no-payload case, but
4655-
// only if case numbering remains unchanged from all resilience domains
4656-
// that can see the enum.
4657-
if (origArgTI->isFixedSize(accessScope) &&
4658-
isa<LoadableTypeInfo>(origArgTI) &&
4659-
cast<LoadableTypeInfo>(origArgTI)->isKnownEmpty()) {
4647+
auto loadableOrigArgTI = dyn_cast<LoadableTypeInfo>(origArgTI);
4648+
if (loadableOrigArgTI && loadableOrigArgTI->isKnownEmpty()) {
46604649
elementsWithNoPayload.push_back({elt, nullptr, nullptr});
46614650
} else {
46624651
// *Now* apply the substitutions and get the type info for the instance's
@@ -4666,20 +4655,16 @@ EnumImplStrategy *EnumImplStrategy::get(TypeConverter &TC,
46664655
auto *substArgTI = &TC.IGM.getTypeInfo(fieldTy);
46674656

46684657
elementsWithPayload.push_back({elt, substArgTI, origArgTI});
4658+
if (!substArgTI->isFixedSize())
4659+
tik = Opaque;
4660+
else if (!substArgTI->isLoadable() && tik > Fixed)
4661+
tik = Fixed;
46694662

4670-
if (!isResilient) {
4671-
if (!substArgTI->isFixedSize(ResilienceScope::Component))
4672-
tik = Opaque;
4673-
else if (!substArgTI->isLoadable() && tik > Fixed)
4674-
tik = Fixed;
4675-
4676-
// If the substituted argument contains a type that is not fixed-size
4677-
// in all resilience domains that have knowledge of this enum's layout,
4678-
// we need to constrain our layout optimizations to what the runtime
4679-
// can reproduce.
4680-
if (!substArgTI->isFixedSize(layoutScope))
4681-
alwaysFixedSize = IsNotFixedSize;
4682-
}
4663+
// If the substituted argument contains a type that is not universally
4664+
// fixed-size, we need to constrain our layout optimizations to what
4665+
// the runtime can reproduce.
4666+
if (!substArgTI->isFixedSize(scope))
4667+
alwaysFixedSize = IsNotFixedSize;
46834668
}
46844669
}
46854670

@@ -4688,7 +4673,12 @@ EnumImplStrategy *EnumImplStrategy::get(TypeConverter &TC,
46884673
+ elementsWithNoPayload.size()
46894674
&& "not all elements accounted for");
46904675

4691-
if (isResilient) {
4676+
// Resilient enums are manipulated as opaque values, except we still
4677+
// make the following assumptions:
4678+
// 1) Physical case indices won't change
4679+
// 2) The indirect-ness of cases won't change
4680+
// 3) Payload types won't change in a non-resilient way
4681+
if (TC.IGM.isResilient(theEnum, ResilienceScope::Component)) {
46924682
return new ResilientEnumImplStrategy(TC.IGM,
46934683
numElements,
46944684
std::move(elementsWithPayload),

lib/IRGen/IRGenModule.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -504,8 +504,6 @@ class IRGenModule {
504504
}
505505

506506
bool isResilient(Decl *decl, ResilienceScope scope);
507-
ResilienceScope getResilienceScopeForAccess(NominalTypeDecl *decl);
508-
ResilienceScope getResilienceScopeForLayout(NominalTypeDecl *decl);
509507

510508
SpareBitVector getSpareBitsForType(llvm::Type *scalarTy, Size size);
511509

test/Inputs/resilient_enum.swift

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ public struct Color {
4040
case Bespoke(Color, Color)
4141
}
4242

43+
// Fixed-layout enum with resilient members
44+
4345
// Resilient enum
4446
public enum Medium {
4547
// Empty cases
@@ -58,21 +60,6 @@ public indirect enum IndirectApproach {
5860
case Angle(Double)
5961
}
6062

61-
// Resilient enum with resilient empty payload case
62-
public struct EmptyStruct {
63-
public init() {}
64-
}
65-
66-
public enum ResilientEnumWithEmptyCase {
67-
case A // should always be case 1
68-
case B // should always be case 2
69-
case Empty(EmptyStruct) // should always be case 0
70-
}
71-
72-
public func getResilientEnumWithEmptyCase() -> [ResilientEnumWithEmptyCase] {
73-
return [.A, .B, .Empty(EmptyStruct())]
74-
}
75-
7663
// Specific enum implementations for executable tests
7764
public enum ResilientEmptyEnum {
7865
case X

test/Interpreter/enum_resilience.swift

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -379,25 +379,4 @@ ResilientEnumTestSuite.test("DynamicLayoutMultiPayload2") {
379379
expectEqual(b, [0, 1, 2, 3])
380380
}
381381

382-
// Make sure case numbers round-trip if payload has zero size
383-
384-
ResilientEnumTestSuite.test("ResilientEnumWithEmptyCase") {
385-
let a: [ResilientEnumWithEmptyCase] = getResilientEnumWithEmptyCase()
386-
387-
let b: [Int] = a.map {
388-
switch $0 {
389-
case .A:
390-
return 0
391-
case .B:
392-
return 1
393-
case .Empty:
394-
return 2
395-
default:
396-
return -1
397-
}
398-
}
399-
400-
expectEqual(b, [0, 1, 2])
401-
}
402-
403382
runAllTests()

0 commit comments

Comments
 (0)