Skip to content

Commit 0243fea

Browse files
authored
Merge pull request #72921 from kubamracek/cp/6.0/embedded-keypath-crash
[6.0 cherry-pick][embedded] Avoid a crash on location-less SIL functions in PerformanceDiagnostics
2 parents 28213cd + 87ecf5c commit 0243fea

File tree

2 files changed

+60
-9
lines changed

2 files changed

+60
-9
lines changed

lib/SILOptimizer/Mandatory/PerformanceDiagnostics.cpp

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -810,15 +810,22 @@ class PerformanceDiagnosticsPass : public SILModuleTransform {
810810
SmallVector<SILFunction *, 8> constructorsAndDestructors;
811811

812812
for (SILFunction &function : *module) {
813-
auto func = function.getLocation().getAsASTNode<AbstractFunctionDecl>();
814-
if (func) {
815-
if (isa<DestructorDecl>(func) || isa<ConstructorDecl>(func)) {
816-
constructorsAndDestructors.push_back(&function);
817-
continue;
818-
}
819-
if (getMethodDispatch(func) == MethodDispatch::Class) {
820-
vtableMembers.push_back(&function);
821-
continue;
813+
// There might be SILFunctions without a location, e.g.
814+
// swift_readAtKeyPath generated by SILGen for keypaths. It's okay to
815+
// skip the ctor/dtor/method detection logic for those, such functions
816+
// still end up in the "others" list and are still visited.
817+
if (function.hasLocation()) {
818+
auto func =
819+
function.getLocation().getAsASTNode<AbstractFunctionDecl>();
820+
if (func) {
821+
if (isa<DestructorDecl>(func) || isa<ConstructorDecl>(func)) {
822+
constructorsAndDestructors.push_back(&function);
823+
continue;
824+
}
825+
if (getMethodDispatch(func) == MethodDispatch::Class) {
826+
vtableMembers.push_back(&function);
827+
continue;
828+
}
822829
}
823830
}
824831

test/embedded/keypath-crash.swift

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// RUN: %target-swift-emit-ir %s -module-name=main -enable-experimental-feature Embedded | %FileCheck %s
2+
3+
// REQUIRES: swift_in_compiler
4+
// REQUIRES: OS=macosx || OS=linux-gnu
5+
6+
@propertyWrapper
7+
@dynamicMemberLookup
8+
public struct Binding<Value> {
9+
public var wrappedValue: Value
10+
11+
init(get: @escaping () -> Value, set: @escaping (Value) -> Void) {
12+
self.wrappedValue = get()
13+
}
14+
15+
subscript<Subject>(dynamicMember keyPath: WritableKeyPath<Value, Subject>) -> Binding<Subject> {
16+
get { fatalError() }
17+
}
18+
}
19+
20+
21+
public struct State<Wrapped> {
22+
public var wrappedValue: Wrapped
23+
24+
public init(wrappedValue: Wrapped) {
25+
self.wrappedValue = wrappedValue
26+
}
27+
public var projectedValue: Projection {
28+
Projection(wrappedValue: wrappedValue)
29+
}
30+
31+
@dynamicMemberLookup
32+
public struct Projection {
33+
var wrappedValue: Wrapped
34+
public subscript<Member>(dynamicMember keyPath: ReferenceWritableKeyPath<Wrapped, Member>) -> Binding<Member> where Wrapped: AnyObject {
35+
Binding(get: {
36+
wrappedValue[keyPath: keyPath]
37+
}, set: { newValue in
38+
wrappedValue[keyPath: keyPath] = newValue
39+
})
40+
}
41+
}
42+
}
43+
44+
// CHECK: define {{.*}}@main(

0 commit comments

Comments
 (0)