Skip to content

Commit 13ecb51

Browse files
committed
embedded: add swift_dynamicCastClass runtime function
To enable dynamic class casts rdar://129672994
1 parent 3dd4198 commit 13ecb51

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

stdlib/public/core/EmbeddedRuntime.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,20 @@ func isValidPointerForNativeRetain(object: Builtin.RawPointer) -> Bool {
187187
public func swift_setDeallocating(object: Builtin.RawPointer) {
188188
}
189189

190+
@_cdecl("swift_dynamicCastClass")
191+
public func swift_dynamicCastClass(object: UnsafeMutableRawPointer, targetMetadata: UnsafeRawPointer) -> UnsafeMutableRawPointer? {
192+
let sourceObj = object.assumingMemoryBound(to: HeapObject.self)
193+
var type = _swift_embedded_get_heap_object_metadata_pointer(sourceObj).assumingMemoryBound(to: ClassMetadata.self)
194+
let targetType = targetMetadata.assumingMemoryBound(to: ClassMetadata.self)
195+
while type != targetType {
196+
guard let superType = type.pointee.superclassMetadata else {
197+
return nil
198+
}
199+
type = UnsafeMutablePointer(superType)
200+
}
201+
return object
202+
}
203+
190204
@_cdecl("swift_isUniquelyReferenced_native")
191205
public func swift_isUniquelyReferenced_native(object: Builtin.RawPointer) -> Bool {
192206
if !isValidPointerForNativeRetain(object: object) { return false }

test/embedded/classes.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,15 @@ class MyClass {
1515
}
1616

1717
class MySubClass: MyClass {
18+
var x = 27
19+
1820
override init() { print("MySubClass.init") }
1921
deinit { print("MySubClass.deinit") }
2022
override func foo() { print("MySubClass.foo") }
23+
24+
func printX() {
25+
print(x)
26+
}
2127
}
2228

2329
class MySubSubClass: MySubClass {
@@ -26,6 +32,17 @@ class MySubSubClass: MySubClass {
2632
override func foo() { print("MySubSubClass.foo") }
2733
}
2834

35+
class OtherSubClass: MyClass {}
36+
37+
func testCasting(_ title: StaticString, _ c: MyClass) {
38+
print(title, terminator: "")
39+
if let s = c as? MySubClass {
40+
s.printX()
41+
} else {
42+
print("-")
43+
}
44+
}
45+
2946
@main
3047
struct Main {
3148
static var o: (MyClass?, MyClass?, MyClass?) = (nil, nil, nil)
@@ -69,5 +86,14 @@ struct Main {
6986
// CHECK: MySubClass.deinit
7087
// CHECK: MyClass.deinit
7188
print("")
89+
90+
// CHECK: base: -
91+
testCasting("base: ", MyClass())
92+
// CHECK: sub: 27
93+
testCasting("sub: ", MySubClass())
94+
// CHECK: subsub: 27
95+
testCasting("subsub: ", MySubSubClass())
96+
// CHECK: other: -
97+
testCasting("other: ", OtherSubClass())
7298
}
7399
}

0 commit comments

Comments
 (0)