Skip to content

Commit 0cadf31

Browse files
authored
Merge pull request #66225 from tshortli/unavailability-cherry-picks-5.9
[5.9] IRGen: Assorted `-unavailable-decl-optimization` fixes
2 parents f618b41 + e5d1471 commit 0cadf31

12 files changed

+134
-21
lines changed

include/swift/SIL/SILModule.h

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

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

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

lib/AST/Availability.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,12 @@ AvailabilityInference::parentDeclForInferredAvailability(const Decl *D) {
181181
return NTD;
182182
}
183183

184-
if (auto *PBD = dyn_cast<PatternBindingDecl>(D))
184+
if (auto *PBD = dyn_cast<PatternBindingDecl>(D)) {
185+
if (PBD->getNumPatternEntries() < 1)
186+
return nullptr;
187+
185188
return PBD->getAnchoringVarDecl(0);
189+
}
186190

187191
if (auto *OTD = dyn_cast<OpaqueTypeDecl>(D))
188192
return OTD->getNamingDecl();

lib/IRGen/GenClass.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1831,6 +1831,9 @@ namespace {
18311831

18321832
void buildMethod(ConstantArrayBuilder &descriptors,
18331833
AbstractFunctionDecl *method) {
1834+
if (Lowering::shouldSkipLowering(method))
1835+
return;
1836+
18341837
auto accessor = dyn_cast<AccessorDecl>(method);
18351838
if (!accessor)
18361839
return emitObjCMethodDescriptor(IGM, descriptors, method);

lib/IRGen/GenDecl.cpp

Lines changed: 7 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()) {
@@ -5484,13 +5486,17 @@ static Address getAddrOfSimpleVariable(IRGenModule &IGM,
54845486
/// The result is always a GlobalValue.
54855487
Address IRGenModule::getAddrOfFieldOffset(VarDecl *var,
54865488
ForDefinition_t forDefinition) {
5489+
assert(!Lowering::shouldSkipLowering(var));
5490+
54875491
LinkEntity entity = LinkEntity::forFieldOffset(var);
54885492
return getAddrOfSimpleVariable(*this, GlobalVars, entity,
54895493
forDefinition);
54905494
}
54915495

54925496
Address IRGenModule::getAddrOfEnumCase(EnumElementDecl *Case,
54935497
ForDefinition_t forDefinition) {
5498+
assert(!Lowering::shouldSkipLowering(Case));
5499+
54945500
LinkEntity entity = LinkEntity::forEnumCase(Case);
54955501
auto addr = getAddrOfSimpleVariable(*this, GlobalVars, entity, forDefinition);
54965502

lib/IRGen/GenEnum.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,9 @@ EnumImplStrategy::getTagIndex(EnumElementDecl *Case) const {
263263
static void emitResilientTagIndex(IRGenModule &IGM,
264264
const EnumImplStrategy *strategy,
265265
EnumElementDecl *Case) {
266+
if (Lowering::shouldSkipLowering(Case))
267+
return;
268+
266269
auto resilientIdx = strategy->getTagIndex(Case);
267270
auto *global = cast<llvm::GlobalVariable>(
268271
IGM.getAddrOfEnumCase(Case, ForDefinition).getAddress());
@@ -6040,6 +6043,13 @@ EnumImplStrategy::get(TypeConverter &TC, SILType type, EnumDecl *theEnum) {
60406043
continue;
60416044
}
60426045

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

lib/IRGen/GenReflection.cpp

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

859-
addField(flags, decl->getArgumentInterfaceType(),
860-
decl->getBaseIdentifier().str());
859+
Type interfaceType = Lowering::shouldSkipLowering(decl)
860+
? nullptr
861+
: decl->getArgumentInterfaceType();
862+
863+
addField(flags, interfaceType, decl->getBaseIdentifier().str());
861864
}
862865

863866
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: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,56 @@
11
// RUN: %target-swift-frontend -parse-as-library -module-name Test -validate-tbd-against-ir=missing %s -emit-ir | %FileCheck %s --check-prefixes=CHECK,CHECK-NO-STRIP
2+
// RUN: %target-swift-frontend -parse-as-library -module-name Test -validate-tbd-against-ir=missing -enable-library-evolution %s -emit-ir | %FileCheck %s --check-prefixes=CHECK,CHECK-NO-STRIP,CHECK-RESILIENT,CHECK-NO-STRIP-RESILIENT
23

34
// RUN: %target-swift-frontend -parse-as-library -module-name Test -validate-tbd-against-ir=missing -unavailable-decl-optimization=complete %s -emit-ir | %FileCheck %s --check-prefixes=CHECK,CHECK-STRIP
5+
// RUN: %target-swift-frontend -parse-as-library -module-name Test -validate-tbd-against-ir=missing -enable-library-evolution -unavailable-decl-optimization=complete %s -emit-ir | %FileCheck %s --check-prefixes=CHECK,CHECK-STRIP,CHECK-RESILIENT,CHECK-STRIP-RESILIENT
46

57
// CHECK: private constant [27 x i8] c"availableEnumAvailableCase\00"
68

79
// FIXME: Should this reflection metadata for an unavailable case be stripped?
810
// CHECK: private constant [29 x i8] c"availableEnumUnavailableCase\00"
911

12+
// CHECK-NO-STRIP-RESILIENT: @"$s4Test13AvailableEnumO09availableC34UnavailableCaseWithAssociatedValueyAcA0E6StructVcACmFWC" = {{.*}}constant
13+
// CHECK-STRIP-RESILIENT-NOT: @"$s4Test13AvailableEnumO09availableC34UnavailableCaseWithAssociatedValueyAcA0E6StructVcACmFWC" =
14+
15+
// CHECK-RESILIENT: @"$s4Test13AvailableEnumO09availablecB4CaseyA2CmFWC" = {{.*}}constant
16+
17+
// CHECK-NO-STRIP-RESILIENT: @"$s4Test13AvailableEnumO09availableC15UnavailableCaseyA2CmFWC" = {{.*}}constant
18+
// CHECK-STRIP-RESILIENT-NOT: @"$s4Test13AvailableEnumO09availableC15UnavailableCaseyA2CmFWC" =
19+
1020
// CHECK-NO-STRIP: private constant [25 x i8] c"unavailableEnumFirstCase\00"
1121
// CHECK-STRIP-NOT: private constant [25 x i8] c"unavailableEnumFirstCase\00"
1222

23+
// CHECK-NO-STRIP-RESILIENT: @"$s4Test15UnavailableEnumO011unavailableC9FirstCaseyA2CmFWC" = {{.*}}constant
24+
// CHECK-STRIP-RESILIENT-NOT: @"$s4Test15UnavailableEnumO011unavailableC9FirstCaseyA2CmFWC"
25+
26+
@available(*, unavailable)
27+
public struct UnavailableStruct {}
1328

1429
public enum AvailableEnum {
1530
case availableEnumAvailableCase
1631

1732
@available(*, unavailable)
1833
case availableEnumUnavailableCase
1934

35+
@available(*, unavailable)
36+
case availableEnumUnavailableCaseWithAssociatedValue(UnavailableStruct)
37+
2038
// CHECK-NO-STRIP: s4Test13AvailableEnumO17unavailableMethodyyF
2139
// CHECK-STRIP-NOT: s4Test13AvailableEnumO17unavailableMethodyyF
2240
@available(*, unavailable)
2341
public func unavailableMethod() {}
24-
25-
// CHECK: s4Test13AvailableEnumO21__derived_enum_equalsySbAC_ACtFZ
26-
// CHECK: s4Test13AvailableEnumO4hash4intoys6HasherVz_tF
27-
// CHECK: s4Test13AvailableEnumO9hashValueSivg
2842
}
2943

44+
// CHECK-NO-STRIP: s4Test17UnavailableStructVMa
45+
// CHECK-STRIP-NOT: s4Test17UnavailableStructVMa
46+
3047
@available(*, unavailable)
3148
public enum UnavailableEnum {
3249
case unavailableEnumFirstCase
3350

3451
// CHECK-NO-STRIP: s4Test15UnavailableEnumO6methodyyF
3552
// CHECK-STRIP-NOT: s4Test15UnavailableEnumO6methodyyF
3653
public func method() {}
37-
38-
// CHECK-NO-STRIP: s4Test15UnavailableEnumO21__derived_enum_equalsySbAC_ACtFZ
39-
// CHECK-STRIP-NOT: s4Test15UnavailableEnumO21__derived_enum_equalsySbAC_ACtFZ
40-
41-
// CHECK-NO-STRIP: s4Test15UnavailableEnumO4hash4intoys6HasherVz_tF
42-
// CHECK-STRIP-NOT: s4Test15UnavailableEnumO4hash4intoys6HasherVz_tF
43-
44-
// CHECK-NO-STRIP: s4Test15UnavailableEnumO9hashValueSivg
45-
// CHECK-STRIP-NOT: s4Test15UnavailableEnumO9hashValueSivg
4654
}
4755

4856
// CHECK: s4Test13AvailableEnumOwug
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -parse-as-library -module-name Test -validate-tbd-against-ir=missing %s -emit-ir | %FileCheck %s --check-prefixes=CHECK,CHECK-NO-STRIP
2+
3+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -parse-as-library -module-name Test -validate-tbd-against-ir=missing -unavailable-decl-optimization=complete %s -emit-ir | %FileCheck %s --check-prefixes=CHECK,CHECK-STRIP
4+
5+
// REQUIRES: objc_interop
6+
7+
import Foundation
8+
9+
public class Class: NSObject {
10+
// CHECK-NO-STRIP: define {{.*}} @"$s4Test5ClassC3fooyyF"
11+
// CHECK-STRIP-NOT: define {{.*}} @"$s4Test5ClassC3fooyyF"
12+
13+
// CHECK-NO-STRIP: define {{.*}} @"$s4Test5ClassC3fooyyFTo"
14+
// CHECK-STRIP-NOT: define {{.*}} @"$s4Test5ClassC3fooyyFTo"
15+
@available(*, unavailable)
16+
@objc public func foo() {}
17+
}
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)