Skip to content

Commit bd91438

Browse files
authored
Merge pull request #74380 from eeckstein/swift_dynamiccastclass-6.0
[6.0] embedded: add swift_dynamicCastClass runtime function
2 parents 858bea9 + b21dce7 commit bd91438

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
@@ -165,6 +165,20 @@ func swift_initStackObject(metadata: UnsafeMutablePointer<ClassMetadata>, object
165165
public func swift_setDeallocating(object: Builtin.RawPointer) {
166166
}
167167

168+
@_cdecl("swift_dynamicCastClass")
169+
public func swift_dynamicCastClass(object: UnsafeMutableRawPointer, targetMetadata: UnsafeRawPointer) -> UnsafeMutableRawPointer? {
170+
let sourceObj = object.assumingMemoryBound(to: HeapObject.self)
171+
var type = _swift_embedded_get_heap_object_metadata_pointer(sourceObj).assumingMemoryBound(to: ClassMetadata.self)
172+
let targetType = targetMetadata.assumingMemoryBound(to: ClassMetadata.self)
173+
while type != targetType {
174+
guard let superType = type.pointee.superclassMetadata else {
175+
return nil
176+
}
177+
type = UnsafeMutablePointer(superType)
178+
}
179+
return object
180+
}
181+
168182
@_cdecl("swift_isUniquelyReferenced_native")
169183
public func swift_isUniquelyReferenced_native(object: Builtin.RawPointer) -> Bool {
170184
if Int(Builtin.ptrtoint_Word(object)) == 0 { 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)