mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
When generic metadata for a class is requested in the same module where
the class is defined, rather than a call to the generic metadata
accessor or to a variant of typeForMangledNode, a call to a new
accessor--a canonical specialized generic metadata accessor--is emitted.
The new function is defined schematically as follows:
MetadataResponse `canonical specialized metadata accessor for C<K>`(MetadataRequest request) {
(void)`canonical specialized metadata accessor for superclass(C<K>)`(::Complete)
(void)`canonical specialized metadata accessor for generic_argument_class(C<K>, 1)`(::Complete)
...
(void)`canonical specialized metadata accessor for generic_argument_class(C<K>, count)`(::Complete)
auto *metadata = objc_opt_self(`canonical specialized metadata for C<K>`);
return {metadata, MetadataState::Complete};
}
where generic_argument_class(C<K>, N) denotes the Nth generic argument
which is both (1) itself a specialized generic type and is also (2) a
class. These calls to the specialized metadata accessors for these
related types ensure that all generic class types are registered with
the Objective-C runtime.
To enable these new canonical specialized generic metadata accessors,
metadata for generic classes is prespecialized as needed. So are the
metaclasses and the corresponding rodata.
Previously, the lazy objc naming hook was registered during process
execution when the first generic class metadata was instantiated. Since
that instantiation may occur "before process launch" (i.e. if the
generic metadata is prespecialized), the lazy naming hook is now
installed at process launch.
178 lines
12 KiB
Swift
178 lines
12 KiB
Swift
public func takes_p1<T: P1>(_: T.Type) {}
|
|
public protocol P1 {
|
|
func normal()
|
|
func generic<T: P3>(_: T)
|
|
}
|
|
public protocol P2 {}
|
|
public protocol P3 {}
|
|
|
|
public struct IsP2: P2 {}
|
|
|
|
public class Base<A> {}
|
|
extension Base: P1 where A: P2 {
|
|
public func normal() {}
|
|
public func generic<T: P3>(_: T) {}
|
|
}
|
|
|
|
// witness method for Base.normal
|
|
|
|
// CHECK-LABEL: define linkonce_odr hidden swiftcc void @"$s32conditional_conformance_subclass4BaseCyxGAA2P1A2A2P2RzlAaEP6normalyyFTW"(%T32conditional_conformance_subclass4BaseC.0** noalias nocapture swiftself dereferenceable(8) %0, %swift.type* %Self, i8** %SelfWitnessTable)
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -1
|
|
// CHECK-NEXT: [[A_P2:%.*]] = load i8*, i8** [[A_P2_PTR]], align 8
|
|
// CHECK-NEXT: %"\CF\84_0_0.P2" = bitcast i8* [[A_P2]] to i8**
|
|
// CHECK-NEXT: [[SELF:%.]] = load %T32conditional_conformance_subclass4BaseC.0*, %T32conditional_conformance_subclass4BaseC.0** %0
|
|
// CHECK-NEXT: call swiftcc void @"$s32conditional_conformance_subclass4BaseCA2A2P2RzlE6normalyyF"(i8** %"\CF\84_0_0.P2", %T32conditional_conformance_subclass4BaseC.0* swiftself [[SELF]])
|
|
// CHECK-NEXT: ret void
|
|
// CHECK-NEXT: }
|
|
|
|
// witness method for Base.generic
|
|
|
|
// CHECK-LABEL: define linkonce_odr hidden swiftcc void @"$s32conditional_conformance_subclass4BaseCyxGAA2P1A2A2P2RzlAaEP7genericyyqd__AA2P3Rd__lFTW"(%swift.opaque* noalias nocapture %0, %swift.type* %"\CF\84_1_0", i8** %"\CF\84_1_0.P3", %T32conditional_conformance_subclass4BaseC.1** noalias nocapture swiftself dereferenceable(8) %1, %swift.type* %Self, i8** %SelfWitnessTable)
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8*, i8** %SelfWitnessTable, i32 -1
|
|
// CHECK-NEXT: [[A_P2:%.*]] = load i8*, i8** [[A_P2_PTR]], align 8
|
|
// CHECK-NEXT: %"\CF\84_0_0.P2" = bitcast i8* [[A_P2]] to i8**
|
|
// CHECK-NEXT: [[SELF:%.]] = load %T32conditional_conformance_subclass4BaseC.1*, %T32conditional_conformance_subclass4BaseC.1** %1, align 8
|
|
// CHECK-NEXT: call swiftcc void @"$s32conditional_conformance_subclass4BaseCA2A2P2RzlE7genericyyqd__AA2P3Rd__lF"(%swift.opaque* noalias nocapture %0, %swift.type* %"\CF\84_1_0", i8** %"\CF\84_0_0.P2", i8** %"\CF\84_1_0.P3", %T32conditional_conformance_subclass4BaseC.1* swiftself [[SELF]])
|
|
// CHECK-NEXT: ret void
|
|
// CHECK-NEXT: }
|
|
|
|
|
|
public class SubclassGeneric<T>: Base<T> {}
|
|
public class SubclassConcrete: Base<IsP2> {}
|
|
public class SubclassGenericConcrete: SubclassGeneric<IsP2> {}
|
|
|
|
public func subclassgeneric_generic<T: P2>(_: T.Type) {
|
|
takes_p1(SubclassGeneric<T>.self)
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( dllexport| protected)?}} swiftcc void @"$s32conditional_conformance_subclass23subclassgeneric_genericyyxmAA2P2RzlF"(%swift.type* %0, %swift.type* %T, i8** %T.P2)
|
|
// CHECK-NEXT: entry:
|
|
// CHECK: %conditional.requirement.buffer = alloca [1 x i8**], align 8
|
|
// CHECK: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s32conditional_conformance_subclass15SubclassGenericCMa"(i64 0, %swift.type* %T)
|
|
// CHECK-NEXT: [[SubclassGeneric_TYPE:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
|
// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
|
|
// CHECK-NEXT: [[T_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
|
|
// CHECK-NEXT: store i8** %T.P2, i8*** [[T_P2_PTR]], align 8
|
|
// CHECK-NEXT: [[Base_P1:%.*]] = call i8** @swift_getWitnessTable
|
|
// CHECK-NEXT: call swiftcc void @"$s32conditional_conformance_subclass8takes_p1yyxmAA2P1RzlF"(%swift.type* [[SubclassGeneric_TYPE]], %swift.type* [[SubclassGeneric_TYPE]], i8** [[Base_P1]])
|
|
// CHECK-NEXT: ret void
|
|
// CHECK-NEXT: }
|
|
|
|
public func subclassgeneric_concrete() {
|
|
takes_p1(SubclassGeneric<IsP2>.self)
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( dllexport| protected)?}} swiftcc void @"$s32conditional_conformance_subclass24subclassgeneric_concreteyyF"()
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[SubclassGeneric_RESPONSE:%.*]] = call {{.*}}@"$s32conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGMb"
|
|
// CHECK-NEXT: [[SubclassGeneric_TYPE:%.*]] = extractvalue %swift.metadata_response [[SubclassGeneric_RESPONSE]], 0
|
|
// CHECK-NEXT: [[Base_P1:%.*]] = call i8** @"$s32conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGAA4BaseCyxGAA2P1A2A0G0RzlWl"()
|
|
// CHECK-NEXT: call swiftcc void @"$s32conditional_conformance_subclass8takes_p1yyxmAA2P1RzlF"(%swift.type* [[SubclassGeneric_TYPE]], %swift.type* [[SubclassGeneric_TYPE]], i8** [[Base_P1]])
|
|
// CHECK-NEXT: ret void
|
|
// CHECK-NEXT: }
|
|
|
|
// Lazy witness table accessor for the concrete SubclassGeneric<IsP2> : Base.
|
|
|
|
// CHECK-LABEL: define linkonce_odr hidden i8** @"$s32conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGAA4BaseCyxGAA2P1A2A0G0RzlWl"()
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: %conditional.requirement.buffer = alloca [1 x i8**], align 8
|
|
// CHECK-NEXT: [[CACHE:%.*]] = load i8**, i8*** @"$s32conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGAA4BaseCyxGAA2P1A2A0G0RzlWL", align 8
|
|
// CHECK-NEXT: [[IS_NULL:%.*]] = icmp eq i8** [[CACHE]], null
|
|
// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
|
|
|
|
// CHECK: cacheIsNull:
|
|
// macosx-NEXT: [[T0:%.*]] = call %swift.type* @__swift_instantiateConcreteTypeFromMangledNameAbstract({ i32, i32 }* @"$s32conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGMD")
|
|
// ios-NEXT: [[T0:%.*]] = call %swift.type* @__swift_instantiateConcreteTypeFromMangledNameAbstract({ i32, i32 }* @"$s32conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGMD")
|
|
// watchos-NEXT: [[T0:%.*]] = call %swift.type* @__swift_instantiateConcreteTypeFromMangledNameAbstract({ i32, i32 }* @"$s32conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGMD")
|
|
// tvos-NEXT: [[T0:%.*]] = call %swift.type* @__swift_instantiateConcreteTypeFromMangledNameAbstract({ i32, i32 }* @"$s32conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGMD")
|
|
// linux-gnu-NEXT: [[T0:%.*]] = call %swift.type* @__swift_instantiateConcreteTypeFromMangledNameAbstract({ i32, i32 }* @"$s32conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGMD")
|
|
// linux-android-NEXT: [[T0:%.*]] = call %swift.type* @__swift_instantiateConcreteTypeFromMangledNameAbstract({ i32, i32 }* @"$s32conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGMD")
|
|
// windows-msvc-NEXT: [[T0:%.*]] = call %swift.type* @__swift_instantiateConcreteTypeFromMangledNameAbstract({ i32, i32 }* @"$s32conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGMD")
|
|
|
|
// CHECK: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
|
|
// CHECK-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
|
|
// CHECK-NEXT: store i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @"$s32conditional_conformance_subclass4IsP2VAA0E0AAWP", i32 0, i32 0), i8*** [[A_P2_PTR]], align 8
|
|
// CHECK-NEXT: [[Base_P1:%.*]] = call i8** @swift_getWitnessTable
|
|
// CHECK-NEXT: store atomic i8** [[Base_P1]], i8*** @"$s32conditional_conformance_subclass15SubclassGenericCyAA4IsP2VGAA4BaseCyxGAA2P1A2A0G0RzlWL" release, align 8
|
|
// CHECK-NEXT: br label %cont
|
|
|
|
// CHECK: cont:
|
|
// CHECK-NEXT: [[T0:%.*]] = phi i8** [ [[CACHE]], %entry ], [ [[Base_P1]], %cacheIsNull ]
|
|
// CHECK-NEXT: ret i8** [[T0]]
|
|
// CHECK-NEXT: }
|
|
|
|
public func subclassconcrete() {
|
|
takes_p1(SubclassConcrete.self)
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( dllexport| protected)?}} swiftcc void @"$s32conditional_conformance_subclass16subclassconcreteyyF"()
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s32conditional_conformance_subclass16SubclassConcreteCMa"(i64 0)
|
|
// CHECK-NEXT: [[SubclassConcrete_TYPE:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
|
// CHECK-NEXT: [[SubclassConcrete_P1:%.*]] = call i8** @"$s32conditional_conformance_subclass16SubclassConcreteCAA4BaseCyxGAA2P1A2A2P2RzlWl"()
|
|
// CHECK-NEXT: call swiftcc void @"$s32conditional_conformance_subclass8takes_p1yyxmAA2P1RzlF"(%swift.type* [[SubclassConcrete_TYPE]], %swift.type* [[SubclassConcrete_TYPE]], i8** [[SubclassConcrete_P1]])
|
|
// CHECK-NEXT: ret void
|
|
// CHECK-NEXT: }
|
|
|
|
// CHECK-LABEL: define linkonce_odr hidden i8** @"$s32conditional_conformance_subclass16SubclassConcreteCAA4BaseCyxGAA2P1A2A2P2RzlWl"()
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: %conditional.requirement.buffer = alloca [1 x i8**], align 8
|
|
// CHECK-NEXT: [[CACHE:%.*]] = load i8**, i8*** @"$s32conditional_conformance_subclass16SubclassConcreteCAA4BaseCyxGAA2P1A2A2P2RzlWL", align 8
|
|
// CHECK-NEXT: [[IS_NULL:%.*]] = icmp eq i8** [[CACHE]], null
|
|
// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
|
|
|
|
// CHECK: cacheIsNull:
|
|
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s32conditional_conformance_subclass16SubclassConcreteCMa"(i64 255)
|
|
// CHECK-NEXT: [[SubclassConcrete_TYPE:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
|
// CHECK-NEXT: extractvalue %swift.metadata_response [[T0]], 1
|
|
|
|
// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
|
|
// CHECK-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
|
|
// CHECK-NEXT: store i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @"$s32conditional_conformance_subclass4IsP2VAA0E0AAWP", i32 0, i32 0), i8*** [[A_P2_PTR]], align 8
|
|
// CHECK-NEXT: [[Base_P1:%.*]] = call i8** @swift_getWitnessTable
|
|
// CHECK-NEXT: store atomic i8** [[Base_P1]], i8*** @"$s32conditional_conformance_subclass16SubclassConcreteCAA4BaseCyxGAA2P1A2A2P2RzlWL" release, align 8
|
|
// CHECK-NEXT: br label %cont
|
|
|
|
// CHECK: cont:
|
|
// CHECK-NEXT: [[T0:%.*]] = phi i8** [ [[CACHE]], %entry ], [ [[Base_P1]], %cacheIsNull ]
|
|
// CHECK-NEXT: ret i8** [[T0]]
|
|
// CHECK-NEXT: }
|
|
|
|
public func subclassgenericconcrete() {
|
|
takes_p1(SubclassGenericConcrete.self)
|
|
}
|
|
|
|
// CHECK-LABEL: define{{( dllexport| protected)?}} swiftcc void @"$s32conditional_conformance_subclass23subclassgenericconcreteyyF"()
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s32conditional_conformance_subclass23SubclassGenericConcreteCMa"(i64 0)
|
|
// CHECK-NEXT: [[SubclassGenericConcrete_TYPE:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
|
// CHECK-NEXT: [[SubclassGenericConcrete_P1:%.*]] = call i8** @"$s32conditional_conformance_subclass23SubclassGenericConcreteCAA4BaseCyxGAA2P1A2A2P2RzlWl"()
|
|
// CHECK-NEXT: call swiftcc void @"$s32conditional_conformance_subclass8takes_p1yyxmAA2P1RzlF"(%swift.type* [[SubclassGenericConcrete_TYPE]], %swift.type* [[SubclassGenericConcrete_TYPE]], i8** [[SubclassGenericConcrete_P1]])
|
|
// CHECK-NEXT: ret void
|
|
// CHECK-NEXT: }
|
|
|
|
// CHECK-LABEL: define linkonce_odr hidden i8** @"$s32conditional_conformance_subclass23SubclassGenericConcreteCAA4BaseCyxGAA2P1A2A2P2RzlWl"()
|
|
// CHECK-NEXT: entry:
|
|
// CHECK-NEXT: %conditional.requirement.buffer = alloca [1 x i8**], align 8
|
|
// CHECK-NEXT: [[CACHE:%.*]] = load i8**, i8*** @"$s32conditional_conformance_subclass23SubclassGenericConcreteCAA4BaseCyxGAA2P1A2A2P2RzlWL", align 8
|
|
// CHECK-NEXT: [[IS_NULL:%.*]] = icmp eq i8** [[CACHE]], null
|
|
// CHECK-NEXT: br i1 [[IS_NULL]], label %cacheIsNull, label %cont
|
|
|
|
// CHECK: cacheIsNull:
|
|
// CHECK-NEXT: [[T0:%.*]] = call swiftcc %swift.metadata_response @"$s32conditional_conformance_subclass23SubclassGenericConcreteCMa"(i64 255)
|
|
// CHECK-NEXT: [[SubclassGenericConcrete_TYPE:%.*]] = extractvalue %swift.metadata_response [[T0]], 0
|
|
// CHECK-NEXT: extractvalue %swift.metadata_response [[T0]], 1
|
|
// CHECK-NEXT: [[CONDITIONAL_REQUIREMENTS:%.*]] = getelementptr inbounds [1 x i8**], [1 x i8**]* %conditional.requirement.buffer, i32 0, i32 0
|
|
// CHECK-NEXT: [[A_P2_PTR:%.*]] = getelementptr inbounds i8**, i8*** [[CONDITIONAL_REQUIREMENTS]], i32 0
|
|
// CHECK-NEXT: store i8** getelementptr inbounds ([1 x i8*], [1 x i8*]* @"$s32conditional_conformance_subclass4IsP2VAA0E0AAWP", i32 0, i32 0), i8*** [[A_P2_PTR]], align 8
|
|
// CHECK-NEXT: [[Base_P1:%.*]] = call i8** @swift_getWitnessTable
|
|
// CHECK-NEXT: store atomic i8** [[Base_P1]], i8*** @"$s32conditional_conformance_subclass23SubclassGenericConcreteCAA4BaseCyxGAA2P1A2A2P2RzlWL" release, align 8
|
|
// CHECK-NEXT: br label %cont
|
|
|
|
// CHECK: cont:
|
|
// CHECK-NEXT: [[T0:%.*]] = phi i8** [ [[CACHE]], %entry ], [ [[Base_P1]], %cacheIsNull ]
|
|
// CHECK-NEXT: ret i8** [[T0]]
|
|
// CHECK-NEXT: }
|