Skip to content

Commit a59f525

Browse files
authored
Merge pull request #66069 from tshortli/unavailable-enum-payloads
IRGen: Exclude unavailable enum cases from runtime layout calculations
2 parents 5c1ce9a + ce97377 commit a59f525

File tree

9 files changed

+89
-11
lines changed

9 files changed

+89
-11
lines changed

include/swift/SIL/SILModule.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1086,11 +1086,11 @@ LLVM_LIBRARY_VISIBILITY bool usesObjCAllocator(ClassDecl *theClass);
10861086
/// Returns true if SIL/IR lowering for the given declaration should be skipped.
10871087
/// A declaration may not require lowering if, for example, it is annotated as
10881088
/// unavailable and optimization settings allow it to be omitted.
1089-
LLVM_LIBRARY_VISIBILITY bool shouldSkipLowering(Decl *D);
1089+
LLVM_LIBRARY_VISIBILITY bool shouldSkipLowering(const Decl *D);
10901090

10911091
/// Returns true if SIL/IR lowering for the given declaration should produce
10921092
/// a stub that traps at runtime because the code ought to be unreachable.
1093-
LLVM_LIBRARY_VISIBILITY bool shouldLowerToUnavailableCodeStub(Decl *D);
1093+
LLVM_LIBRARY_VISIBILITY bool shouldLowerToUnavailableCodeStub(const Decl *D);
10941094
} // namespace Lowering
10951095

10961096
/// Apply the given function to each ABI member of \c D skipping the members

lib/IRGen/GenDecl.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1568,7 +1568,9 @@ void IRGenerator::noteUseOfTypeGlobals(NominalTypeDecl *type,
15681568
RequireMetadata_t requireMetadata) {
15691569
if (!type)
15701570
return;
1571-
1571+
1572+
assert(!Lowering::shouldSkipLowering(type));
1573+
15721574
// Force emission of ObjC protocol descriptors used by type refs.
15731575
if (auto proto = dyn_cast<ProtocolDecl>(type)) {
15741576
if (proto->isObjC()) {

lib/IRGen/GenEnum.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6040,6 +6040,13 @@ EnumImplStrategy::get(TypeConverter &TC, SILType type, EnumDecl *theEnum) {
60406040
continue;
60416041
}
60426042

6043+
// For the purposes of memory layout, treat unavailable cases as if they do
6044+
// not have a payload.
6045+
if (Lowering::shouldSkipLowering(elt)) {
6046+
elementsWithNoPayload.push_back({elt, nullptr, nullptr});
6047+
continue;
6048+
}
6049+
60436050
// If the payload is indirect, we can use the NativeObject type metadata
60446051
// without recurring. The box won't affect loadability or fixed-ness.
60456052
if (elt->isIndirect() || theEnum->isIndirect()) {

lib/IRGen/GenReflection.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -854,8 +854,11 @@ class FieldTypeMetadataBuilder : public ReflectionMetadataBuilder {
854854
if (hasPayload && (decl->isIndirect() || enumDecl->isIndirect()))
855855
flags.setIsIndirectCase();
856856

857-
addField(flags, decl->getArgumentInterfaceType(),
858-
decl->getBaseIdentifier().str());
857+
Type interfaceType = Lowering::shouldSkipLowering(decl)
858+
? nullptr
859+
: decl->getArgumentInterfaceType();
860+
861+
addField(flags, interfaceType, decl->getBaseIdentifier().str());
859862
}
860863

861864
void layoutEnum() {

lib/IRGen/IRGenModule.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
#include "swift/IRGen/ValueWitness.h"
3737
#include "swift/SIL/RuntimeEffect.h"
3838
#include "swift/SIL/SILFunction.h"
39+
#include "swift/SIL/SILModule.h"
3940
#include "llvm/ADT/DenseMap.h"
4041
#include "llvm/ADT/DenseSet.h"
4142
#include "llvm/ADT/Hashing.h"
@@ -455,6 +456,7 @@ class IRGenerator {
455456
}
456457

457458
void noteLazyReemissionOfNominalTypeDescriptor(NominalTypeDecl *decl) {
459+
assert(!Lowering::shouldSkipLowering(decl));
458460
LazilyReemittedTypeContextDescriptors.insert(decl);
459461
}
460462

@@ -464,6 +466,7 @@ class IRGenerator {
464466
}
465467

466468
void noteUseOfMetadataAccessor(NominalTypeDecl *decl) {
469+
assert(!Lowering::shouldSkipLowering(decl));
467470
if (LazyMetadataAccessors.count(decl) == 0) {
468471
LazyMetadataAccessors.insert(decl);
469472
}

lib/IRGen/MetadataLayout.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include "TupleMetadataVisitor.h"
3535

3636
#include "swift/Basic/LLVM.h"
37+
#include "swift/SIL/SILModule.h"
3738
#include "llvm/ADT/Optional.h"
3839

3940
using namespace swift;

lib/SIL/IR/SILModule.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -956,7 +956,7 @@ bool Lowering::usesObjCAllocator(ClassDecl *theClass) {
956956
return theClass->getObjectModel() == ReferenceCounting::ObjC;
957957
}
958958

959-
bool Lowering::shouldSkipLowering(Decl *D) {
959+
bool Lowering::shouldSkipLowering(const Decl *D) {
960960
if (D->getASTContext().LangOpts.UnavailableDeclOptimizationMode !=
961961
UnavailableDeclOptimization::Complete)
962962
return false;
@@ -966,7 +966,7 @@ bool Lowering::shouldSkipLowering(Decl *D) {
966966
return D->getSemanticUnavailableAttr() != None;
967967
}
968968

969-
bool Lowering::shouldLowerToUnavailableCodeStub(Decl *D) {
969+
bool Lowering::shouldLowerToUnavailableCodeStub(const Decl *D) {
970970
if (D->getASTContext().LangOpts.UnavailableDeclOptimizationMode !=
971971
UnavailableDeclOptimization::Stub)
972972
return false;

test/IRGen/unavailable_decl_optimization_complete_enum.swift

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,27 @@
1010
// CHECK-NO-STRIP: private constant [25 x i8] c"unavailableEnumFirstCase\00"
1111
// CHECK-STRIP-NOT: private constant [25 x i8] c"unavailableEnumFirstCase\00"
1212

13+
@available(*, unavailable)
14+
public struct UnavailableStruct {}
1315

1416
public enum AvailableEnum {
1517
case availableEnumAvailableCase
1618

1719
@available(*, unavailable)
1820
case availableEnumUnavailableCase
1921

22+
@available(*, unavailable)
23+
case availableEnumUnavailableCaseWithAssociatedValue(UnavailableStruct)
24+
2025
// CHECK-NO-STRIP: s4Test13AvailableEnumO17unavailableMethodyyF
2126
// CHECK-STRIP-NOT: s4Test13AvailableEnumO17unavailableMethodyyF
2227
@available(*, unavailable)
2328
public func unavailableMethod() {}
24-
25-
// CHECK: s4Test13AvailableEnumO21__derived_enum_equalsySbAC_ACtFZ
26-
// CHECK: s4Test13AvailableEnumO4hash4intoys6HasherVz_tF
27-
// CHECK: s4Test13AvailableEnumO9hashValueSivg
2829
}
2930

31+
// CHECK-NO-STRIP: s4Test17UnavailableStructVMa
32+
// CHECK-STRIP-NOT: s4Test17UnavailableStructVMa
33+
3034
@available(*, unavailable)
3135
public enum UnavailableEnum {
3236
case unavailableEnumFirstCase
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift %s -Xfrontend -unavailable-decl-optimization=complete -o %t/a.out
3+
// RUN: %target-codesign %t/a.out
4+
// RUN: %target-run %t/a.out
5+
// REQUIRES: executable_test
6+
7+
import StdlibUnittest
8+
9+
@available(*, unavailable)
10+
class UnavailableClass {
11+
var x: UInt8 = 0
12+
}
13+
14+
enum SingletonTrivial {
15+
@available(*, unavailable)
16+
case unavailable(UInt8)
17+
}
18+
19+
enum SingletonClass {
20+
@available(*, unavailable)
21+
case unavailable(UnavailableClass)
22+
}
23+
24+
enum NoPayload {
25+
case x
26+
@available(*, unavailable)
27+
case unavailable
28+
case y
29+
}
30+
31+
enum SinglePayloadTrivial {
32+
case x
33+
@available(*, unavailable)
34+
case unavailable(UInt8)
35+
case y
36+
}
37+
38+
enum MultiPayloadTrivial {
39+
case x(UInt8)
40+
@available(*, unavailable)
41+
case unavailable(UInt8, UInt8)
42+
case y
43+
}
44+
45+
enum MultiPayloadGeneric<T, U> {
46+
case x(T)
47+
@available(*, unavailable)
48+
case unavailable(T, U)
49+
case y
50+
}
51+
52+
expectEqual(MemoryLayout<SingletonTrivial>.size, 0)
53+
expectEqual(MemoryLayout<SingletonClass>.size, 0)
54+
expectEqual(MemoryLayout<NoPayload>.size, 1)
55+
expectEqual(MemoryLayout<SinglePayloadTrivial>.size, 1)
56+
expectEqual(MemoryLayout<MultiPayloadTrivial>.size, 2)
57+
expectEqual(MemoryLayout<MultiPayloadGeneric<UInt8, UInt8>>.size, 2)
58+
expectEqual(MemoryLayout<MultiPayloadGeneric<UInt32, UInt32>>.size, 5)

0 commit comments

Comments
 (0)