Skip to content

Commit 3bdb924

Browse files
authored
Merge pull request #23846 from slavapestov/class-stub-fix-and-tests
Class stub fixes and execution tests
2 parents c6efc8d + 7c8641c commit 3bdb924

16 files changed

+248
-90
lines changed

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 19 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -2084,13 +2084,6 @@ TypeDecl *EquivalenceClass::lookupNestedType(
20842084
foundMembers);
20852085
for (auto member : foundMembers) {
20862086
if (auto type = dyn_cast<TypeDecl>(member)) {
2087-
// Resolve the signature of this type.
2088-
if (!type->hasInterfaceType()) {
2089-
type->getASTContext().getLazyResolver()->resolveDeclSignature(type);
2090-
if (!type->hasInterfaceType())
2091-
continue;
2092-
}
2093-
20942087
concreteDecls.push_back(type);
20952088
}
20962089
}
@@ -3812,25 +3805,31 @@ PotentialArchetype *GenericSignatureBuilder::realizePotentialArchetype(
38123805
return pa;
38133806
}
38143807

3808+
static Type getStructuralType(TypeDecl *typeDecl, LazyResolver *resolver) {
3809+
if (auto typealias = dyn_cast<TypeAliasDecl>(typeDecl)) {
3810+
// Resolve the underlying type, if we haven't done so yet.
3811+
if (!typealias->hasInterfaceType())
3812+
resolver->resolveDeclSignature(typealias);
3813+
3814+
return typealias->getUnderlyingTypeLoc().getType();
3815+
}
3816+
3817+
return typeDecl->getDeclaredInterfaceType();
3818+
}
3819+
38153820
static Type substituteConcreteType(GenericSignatureBuilder &builder,
38163821
PotentialArchetype *basePA,
38173822
TypeDecl *concreteDecl) {
38183823
assert(concreteDecl);
38193824

38203825
auto *proto = concreteDecl->getDeclContext()->getSelfProtocolDecl();
38213826

3822-
if (!concreteDecl->hasInterfaceType())
3823-
builder.getLazyResolver()->resolveDeclSignature(concreteDecl);
3824-
3825-
if (!concreteDecl->hasInterfaceType())
3827+
// Form an unsubstituted type referring to the given type declaration,
3828+
// for use in an inferred same-type requirement.
3829+
auto type = getStructuralType(concreteDecl, builder.getLazyResolver());
3830+
if (!type)
38263831
return Type();
38273832

3828-
// The protocol concrete type has an underlying type written in terms
3829-
// of the protocol's 'Self' type.
3830-
auto typealias = dyn_cast<TypeAliasDecl>(concreteDecl);
3831-
auto type = typealias ? typealias->getUnderlyingTypeLoc().getType()
3832-
: concreteDecl->getDeclaredInterfaceType();
3833-
38343833
Type parentType;
38353834
SubstitutionMap subMap;
38363835
if (proto) {
@@ -3855,7 +3854,7 @@ static Type substituteConcreteType(GenericSignatureBuilder &builder,
38553854
}
38563855

38573856
// If we had a typealias, form a sugared type.
3858-
if (typealias) {
3857+
if (auto *typealias = dyn_cast<TypeAliasDecl>(concreteDecl)) {
38593858
type = TypeAliasType::get(typealias, parentType, subMap, type);
38603859
}
38613860

@@ -4226,34 +4225,13 @@ ConstraintResult GenericSignatureBuilder::expandConformanceRequirement(
42264225
return result;
42274226
};
42284227

4229-
// Form an unsubstituted type referring to the given type declaration,
4230-
// for use in an inferred same-type requirement.
4231-
auto formUnsubstitutedType = [&](TypeDecl *typeDecl) -> Type {
4232-
if (auto assocType = dyn_cast<AssociatedTypeDecl>(typeDecl)) {
4233-
return DependentMemberType::get(
4234-
assocType->getProtocol()->getSelfInterfaceType(),
4235-
assocType);
4236-
}
4237-
4238-
// Resolve the underlying type, if we haven't done so yet.
4239-
if (!typeDecl->hasInterfaceType()) {
4240-
getLazyResolver()->resolveDeclSignature(typeDecl);
4241-
}
4242-
4243-
if (auto typealias = dyn_cast<TypeAliasDecl>(typeDecl)) {
4244-
return typealias->getUnderlyingTypeLoc().getType();
4245-
}
4246-
4247-
return typeDecl->getDeclaredInterfaceType();
4248-
};
4249-
42504228
// An inferred same-type requirement between the two type declarations
42514229
// within this protocol or a protocol it inherits.
42524230
auto addInferredSameTypeReq = [&](TypeDecl *first, TypeDecl *second) {
4253-
Type firstType = formUnsubstitutedType(first);
4231+
Type firstType = getStructuralType(first, getLazyResolver());
42544232
if (!firstType) return;
42554233

4256-
Type secondType = formUnsubstitutedType(second);
4234+
Type secondType = getStructuralType(second, getLazyResolver());
42574235
if (!secondType) return;
42584236

42594237
auto inferredSameTypeSource =
@@ -5170,11 +5148,6 @@ ConstraintResult GenericSignatureBuilder::addInheritedRequirements(
51705148
UnresolvedType type,
51715149
const RequirementSource *parentSource,
51725150
ModuleDecl *inferForModule) {
5173-
if (isa<AssociatedTypeDecl>(decl) &&
5174-
decl->hasInterfaceType() &&
5175-
decl->getInterfaceType()->is<ErrorType>())
5176-
return ConstraintResult::Resolved;
5177-
51785151
// Local function to get the source.
51795152
auto getFloatingSource = [&](const TypeRepr *typeRepr, bool forInferred) {
51805153
if (parentSource) {

lib/IRGen/GenCast.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,7 @@ FailableCastResult irgen::emitClassIdenticalCast(IRGenFunction &IGF,
107107
llvm::Value *targetMetadata;
108108
if ((targetMetadata =
109109
tryEmitConstantHeapMetadataRef(IGF.IGM, toType.getASTType(),
110-
/*allowUninitialized*/ false,
111-
/*allowStub*/ false))) {
110+
/*allowUninitialized*/ false))) {
112111
// ok
113112
} else {
114113
targetMetadata

lib/IRGen/GenClass.cpp

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,7 +1194,32 @@ namespace {
11941194
if (categoryCount > 0)
11951195
os << categoryCount;
11961196
}
1197-
1197+
1198+
llvm::Constant *getClassMetadataRef() {
1199+
auto *theClass = getClass();
1200+
1201+
if (theClass->hasClangNode())
1202+
return IGM.getAddrOfObjCClass(theClass, NotForDefinition);
1203+
1204+
// Note that getClassMetadataStrategy() will return
1205+
// ClassMetadataStrategy::Resilient if the class is
1206+
// from another resilience domain, even if inside that
1207+
// resilience domain the class has fixed metadata
1208+
// layout.
1209+
//
1210+
// Since a class only has a class stub if its class
1211+
// hierarchy crosses resilience domains, we use a
1212+
// slightly different query here.
1213+
if (theClass->checkAncestry(AncestryFlags::ResilientOther)) {
1214+
assert(IGM.Context.LangOpts.EnableObjCResilientClassStubs);
1215+
return IGM.getAddrOfObjCResilientClassStub(theClass, NotForDefinition,
1216+
TypeMetadataAddress::AddressPoint);
1217+
}
1218+
1219+
auto type = getSelfType(theClass).getASTType();
1220+
return tryEmitConstantHeapMetadataRef(IGM, type, /*allowUninit*/ true);
1221+
}
1222+
11981223
public:
11991224
llvm::Constant *emitCategory() {
12001225
assert(TheExtension && "can't emit category data for a class");
@@ -1205,18 +1230,7 @@ namespace {
12051230
// char const *name;
12061231
fields.add(IGM.getAddrOfGlobalString(CategoryName));
12071232
// const class_t *theClass;
1208-
if (getClass()->hasClangNode())
1209-
fields.add(IGM.getAddrOfObjCClass(getClass(), NotForDefinition));
1210-
else {
1211-
auto type = getSelfType(getClass()).getASTType();
1212-
llvm::Constant *metadata =
1213-
tryEmitConstantHeapMetadataRef(IGM, type,
1214-
/*allowUninit*/ true,
1215-
/*allowStub*/ true);
1216-
assert(metadata &&
1217-
"extended objc class doesn't have constant metadata?");
1218-
fields.add(metadata);
1219-
}
1233+
fields.add(getClassMetadataRef());
12201234
// const method_list_t *instanceMethods;
12211235
fields.add(buildInstanceMethodList());
12221236
// const method_list_t *classMethods;

lib/IRGen/GenDecl.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -928,6 +928,12 @@ void IRGenModule::emitGlobalLists() {
928928
"regular,no_dead_strip"),
929929
llvm::GlobalValue::InternalLinkage, Int8PtrTy, false);
930930

931+
// And categories on class stubs.
932+
emitGlobalList(*this, ObjCCategoriesOnStubs, "objc_categories_stubs",
933+
GetObjCSectionName("__objc_catlist2",
934+
"regular,no_dead_strip"),
935+
llvm::GlobalValue::InternalLinkage, Int8PtrTy, false);
936+
931937
// Emit nonlazily realized class references in a second magic section to make
932938
// sure they are realized by the Objective-C runtime before any instances
933939
// are allocated.
@@ -3802,7 +3808,15 @@ void IRGenModule::emitExtension(ExtensionDecl *ext) {
38023808
"foreign types cannot have categories emitted");
38033809
llvm::Constant *category = emitCategoryData(*this, ext);
38043810
category = llvm::ConstantExpr::getBitCast(category, Int8PtrTy);
3805-
ObjCCategories.push_back(category);
3811+
3812+
auto *theClass = ext->getSelfClassDecl();
3813+
3814+
// Categories on class stubs are added to a separate list.
3815+
if (theClass->checkAncestry(AncestryFlags::ResilientOther))
3816+
ObjCCategoriesOnStubs.push_back(category);
3817+
else
3818+
ObjCCategories.push_back(category);
3819+
38063820
ObjCCategoryDecls.push_back(ext);
38073821
}
38083822
}

lib/IRGen/GenMeta.cpp

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,6 +1399,7 @@ namespace {
13991399
super::layout();
14001400
addVTable();
14011401
addOverrideTable();
1402+
addObjCResilientClassStubInfo();
14021403
}
14031404

14041405
void addIncompleteMetadataOrRelocationFunction() {
@@ -1632,6 +1633,20 @@ namespace {
16321633
// uint32_t FieldOffsetVectorOffset;
16331634
B.addInt32(getFieldVectorOffset() / IGM.getPointerSize());
16341635
}
1636+
1637+
void addObjCResilientClassStubInfo() {
1638+
if (IGM.getClassMetadataStrategy(getType()) !=
1639+
ClassMetadataStrategy::Resilient)
1640+
return;
1641+
1642+
if (!hasObjCResilientClassStub(IGM, getType()))
1643+
return;
1644+
1645+
B.addRelativeAddress(
1646+
IGM.getAddrOfObjCResilientClassStub(
1647+
getType(), NotForDefinition,
1648+
TypeMetadataAddress::AddressPoint));
1649+
}
16351650
};
16361651

16371652
class OpaqueTypeDescriptorBuilder
@@ -2634,8 +2649,7 @@ namespace {
26342649
Type type = Target->mapTypeIntoContext(Target->getSuperclass());
26352650
auto *metadata = tryEmitConstantHeapMetadataRef(
26362651
IGM, type->getCanonicalType(),
2637-
/*allowUninit*/ false,
2638-
/*allowStub*/ false);
2652+
/*allowUninit*/ false);
26392653
assert(metadata != nullptr);
26402654
B.add(metadata);
26412655
}
@@ -3231,12 +3245,6 @@ void irgen::emitClassMetadata(IRGenModule &IGM, ClassDecl *classDecl,
32313245
classDecl, NotForDefinition,
32323246
TypeMetadataAddress::AddressPoint);
32333247
emitObjCClassSymbol(IGM, classDecl, stub);
3234-
3235-
// @_objc_non_lazy_realization is only for use by the standard
3236-
// library, and we cannot support it with Objective-C class
3237-
// stubs (which there are none of in the standard library).
3238-
assert(!classDecl->getAttrs().hasAttribute<ObjCNonLazyRealizationAttr>());
3239-
IGM.addObjCClass(stub, /*eagerInitialization=*/false);
32403248
}
32413249
}
32423250
break;

lib/IRGen/IRGenModule.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -987,6 +987,8 @@ class IRGenModule {
987987
SmallVector<llvm::WeakTrackingVH, 4> ObjCNonLazyClasses;
988988
/// List of Objective-C categories, bitcast to i8*.
989989
SmallVector<llvm::WeakTrackingVH, 4> ObjCCategories;
990+
/// List of Objective-C categories on class stubs, bitcast to i8*.
991+
SmallVector<llvm::WeakTrackingVH, 4> ObjCCategoriesOnStubs;
990992
/// List of non-ObjC protocols described by this module.
991993
SmallVector<ProtocolDecl *, 4> SwiftProtocols;
992994
/// List of protocol conformances to generate descriptors for.

lib/IRGen/MetadataRequest.cpp

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -517,19 +517,12 @@ irgen::getRuntimeReifiedType(IRGenModule &IGM, CanType type) {
517517
llvm::Constant *
518518
irgen::tryEmitConstantHeapMetadataRef(IRGenModule &IGM,
519519
CanType type,
520-
bool allowDynamicUninitialized,
521-
bool allowStub) {
520+
bool allowDynamicUninitialized) {
522521
auto theDecl = type->getClassOrBoundGenericClass();
523522
assert(theDecl && "emitting constant heap metadata ref for non-class type?");
524523

525524
switch (IGM.getClassMetadataStrategy(theDecl)) {
526525
case ClassMetadataStrategy::Resilient:
527-
if (allowStub && IGM.Context.LangOpts.EnableObjCResilientClassStubs) {
528-
return IGM.getAddrOfObjCResilientClassStub(theDecl, NotForDefinition,
529-
TypeMetadataAddress::AddressPoint);
530-
}
531-
return nullptr;
532-
533526
case ClassMetadataStrategy::Singleton:
534527
if (!allowDynamicUninitialized)
535528
return nullptr;

lib/IRGen/MetadataRequest.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -592,8 +592,7 @@ CanType getRuntimeReifiedType(IRGenModule &IGM, CanType type);
592592
/// by a constant.
593593
llvm::Constant *tryEmitConstantHeapMetadataRef(IRGenModule &IGM,
594594
CanType type,
595-
bool allowUninitialized,
596-
bool allowStub);
595+
bool allowUninitialized);
597596

598597
enum class MetadataValueType { ObjCClass, TypeMetadata };
599598

test/IRGen/class_update_callback_with_stub.swift

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
// RUN: %target-swift-frontend -emit-module -enable-library-evolution -emit-module-path=%t/resilient_struct.swiftmodule -I %t %S/../Inputs/resilient_struct.swift
44
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-module-path %t/resilient_class.swiftmodule -enable-library-evolution %S/../Inputs/resilient_class.swift
55
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -emit-module-path %t/resilient_objc_class.swiftmodule -enable-library-evolution %S/../Inputs/resilient_objc_class.swift
6-
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -I %t -emit-ir -enable-library-evolution -enable-resilient-objc-class-stubs %s | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-%target-runtime -DINT=i%target-ptrsize
6+
// RUN: %target-swift-frontend(mock-sdk: -sdk %S/Inputs -I %t) -I %t -emit-ir -enable-library-evolution -enable-resilient-objc-class-stubs %s > %t/out
7+
// RUN: %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize --check-prefix=CHECK-%target-runtime -DINT=i%target-ptrsize < %t/out
8+
// RUN: %FileCheck %s --check-prefix=NEGATIVE < %t/out
79

810
import Foundation
911
import resilient_class
@@ -49,6 +51,8 @@ import resilient_objc_class
4951
// CHECK-SAME: @"got.$s15resilient_class22ResilientOutsideParentCMn"
5052
// CHECK-SAME: @"got.$s15resilient_class22ResilientOutsideParentCACycfCTq"
5153
// CHECK-SAME: @"$s31class_update_callback_with_stub17ResilientSubclassCACycfC"
54+
// -- class stub
55+
// CHECK-SAME: @"$s31class_update_callback_with_stub17ResilientSubclassCMt"
5256
// CHECK-SAME: }>, section "__TEXT,__const", align 4
5357

5458

@@ -87,22 +91,27 @@ import resilient_objc_class
8791
// CHECK-LABEL: @"_CATEGORY__TtC31class_update_callback_with_stub27FixedLayoutNSObjectSubclass_$_class_update_callback_with_stub" = private constant
8892
// CHECK-SAME: @"$s31class_update_callback_with_stub27FixedLayoutNSObjectSubclassCMs"
8993

94+
// -- But not if the entire inheritance chain is in a single module
9095

91-
// -- The NSObject-derived class appears on the class list
96+
// CHECK-LABEL: @"_CATEGORY__TtC15resilient_class22ResilientOutsideParent_$_class_update_callback_with_stub" = private constant
97+
// CHECK-SAME: @"$s15resilient_class22ResilientOutsideParentCN"
9298

93-
// CHECK-LABEL: @objc_classes = internal global
94-
// CHECK-SAME: @"$s31class_update_callback_with_stub25ResilientNSObjectSubclassCMs"
95-
// CHECK-SAME: @"$s31class_update_callback_with_stub27FixedLayoutNSObjectSubclassCMs"
96-
// CHECK-SAME: , section "__DATA,__objc_classlist,regular,no_dead_strip"
9799

100+
// -- Class stubs do not appear in the class list
101+
102+
// NEGATIVE-NOT: @objc_classes =
98103

99104
// -- The category list
100105

101106
// CHECK-LABEL: @objc_categories = internal global
107+
// CHECK-SAME: @"_CATEGORY__TtC15resilient_class22ResilientOutsideParent_$_class_update_callback_with_stub"
108+
// CHECK-SAME: , section "__DATA,__objc_catlist,regular,no_dead_strip"
109+
110+
// CHECK-LABEL: @objc_categories_stubs = internal global
102111
// CHECK-SAME: @"_CATEGORY__TtC31class_update_callback_with_stub17ResilientSubclass_$_class_update_callback_with_stub"
103112
// CHECK-SAME: @"_CATEGORY__TtC31class_update_callback_with_stub25ResilientNSObjectSubclass_$_class_update_callback_with_stub"
104113
// CHECK-SAME: @"_CATEGORY__TtC31class_update_callback_with_stub27FixedLayoutNSObjectSubclass_$_class_update_callback_with_stub"
105-
// CHECK-SAME: , section "__DATA,__objc_catlist,regular,no_dead_strip"
114+
// CHECK-SAME: , section "__DATA,__objc_catlist2,regular,no_dead_strip"
106115

107116

108117
// -- Address point for class stubs
@@ -152,4 +161,8 @@ extension ResilientNSObjectSubclass {
152161

153162
extension FixedLayoutNSObjectSubclass {
154163
@objc public func objcMethod() {}
155-
}
164+
}
165+
166+
extension ResilientOutsideParent {
167+
@objc public func anObjcMethod() {}
168+
}

test/Interpreter/SDK/objc_getClass.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import resilient_objc_class
3030
// Old OS versions do not have this hook.
3131
let getClassHookMissing = {
3232
nil == dlsym(UnsafeMutableRawPointer(bitPattern: -2),
33-
"objc_setHook_getClass")
33+
"objc_setHook_getClass")
3434
}()
3535

3636
var testSuite = TestSuite("objc_getClass")

test/Interpreter/class_resilience.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
// RUN: %target-run %t/main2 %t/%target-library-name(resilient_struct_wmo) %t/%target-library-name(resilient_class_wmo) %t/%target-library-name(fixed_layout_class_wmo)
3030

3131
// REQUIRES: executable_test
32-
// REQUIRES: rdar49026933
3332

3433
import StdlibUnittest
3534

0 commit comments

Comments
 (0)