Skip to content

Commit b8bd832

Browse files
committed
[embedded] Add IVarDestroyers into class metadata, add support for throws in initializers
1 parent 55c4956 commit b8bd832

File tree

9 files changed

+128
-10
lines changed

9 files changed

+128
-10
lines changed

lib/IRGen/ClassMetadataVisitor.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ template <class Impl> class ClassMetadataVisitor
7676
asImpl().noteAddressPoint();
7777
asImpl().addEmbeddedSuperclass(classTy);
7878
asImpl().addDestructorFunction();
79+
asImpl().addIVarDestroyer();
7980
addEmbeddedClassMembers(Target);
8081
}
8182

@@ -87,6 +88,7 @@ template <class Impl> class ClassMetadataVisitor
8788
asImpl().noteAddressPoint();
8889
asImpl().addSuperclass();
8990
asImpl().addDestructorFunction();
91+
asImpl().addIVarDestroyer();
9092
addEmbeddedClassMembers(Target);
9193
return;
9294
}

lib/IRGen/GenMeta.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4023,6 +4023,23 @@ namespace {
40234023
}
40244024

40254025
void addIVarDestroyer() {
4026+
if (IGM.Context.LangOpts.hasFeature(Feature::Embedded)) {
4027+
llvm::Constant *ptr = nullptr;
4028+
for (const SILVTable::Entry &entry : VTable->getEntries()) {
4029+
if (entry.getMethod().kind == SILDeclRef::Kind::IVarDestroyer) {
4030+
ptr = IGM.getAddrOfSILFunction(entry.getImplementation(), NotForDefinition);
4031+
break;
4032+
}
4033+
}
4034+
if (ptr) {
4035+
B.addSignedPointer(ptr, IGM.getOptions().PointerAuth.HeapDestructors,
4036+
PointerAuthEntity::Special::HeapDestructor);
4037+
} else {
4038+
B.addNullPointer(IGM.FunctionPtrTy);
4039+
}
4040+
return;
4041+
}
4042+
40264043
if (asImpl().getFieldLayout().hasObjCImplementation())
40274044
return;
40284045

stdlib/public/SwiftShims/swift/shims/EmbeddedShims.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,20 @@ _swift_embedded_invoke_heap_object_destroy(void *object) {
6262
#endif
6363
}
6464

65+
static inline void
66+
_swift_embedded_invoke_heap_object_ivardestroyer(void *object, void *metadata) {
67+
void **ivardestroyer_location = &((void **)metadata)[2];
68+
#if __has_feature(ptrauth_calls)
69+
(*(HeapObjectDestroyer __ptrauth(0, 1, 0xbbbf) *)ivardestroyer_location)(object);
70+
#else
71+
(*(HeapObjectDestroyer *)ivardestroyer_location)(object);
72+
#endif
73+
}
74+
75+
static inline void *_swift_embedded_get_heap_object_metadata_pointer(void *object) {
76+
return ((EmbeddedHeapObject *)object)->metadata;
77+
}
78+
6579
static inline void _swift_embedded_set_heap_object_metadata_pointer(void *object, void *metadata) {
6680
((EmbeddedHeapObject *)object)->metadata = metadata;
6781
}

stdlib/public/core/EmbeddedRuntime.swift

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,15 @@ import SwiftShims
1717
public struct ClassMetadata {
1818
var superclassMetadata: UnsafeMutablePointer<ClassMetadata>?
1919

20-
// There is no way to express the actual calling convention on the heap desroy
20+
// There is no way to express the actual calling convention on this
2121
// function (swiftcc with 'self') currently, so let's use UnsafeRawPointer
2222
// and a helper function in C (_swift_embedded_invoke_heap_object_destroy).
2323
var destroy: UnsafeRawPointer
24+
25+
// There is no way to express the actual calling convention on this
26+
// function (swiftcc with 'self') currently, so let's use UnsafeRawPointer
27+
// and a helper function in C (_swift_embedded_invoke_heap_object_ivardestroyer).
28+
var ivarDestroyer: UnsafeRawPointer
2429
}
2530

2631
public struct HeapObject {
@@ -116,6 +121,20 @@ func swift_deallocClassInstance(object: UnsafeMutablePointer<HeapObject>, alloca
116121
free(object._rawValue)
117122
}
118123

124+
@_cdecl("swift_deallocPartialClassInstance")
125+
public func swift_deallocPartialClassInstance(object: Builtin.RawPointer, metadata: Builtin.RawPointer, allocatedSize: Int, allocatedAlignMask: Int) {
126+
swift_deallocPartialClassInstance(object: UnsafeMutablePointer<HeapObject>(object), metadata: UnsafeMutablePointer<ClassMetadata>(metadata), allocatedSize: allocatedSize, allocatedAlignMask: allocatedAlignMask)
127+
}
128+
129+
func swift_deallocPartialClassInstance(object: UnsafeMutablePointer<HeapObject>, metadata: UnsafeMutablePointer<ClassMetadata>, allocatedSize: Int, allocatedAlignMask: Int) {
130+
var classMetadata = _swift_embedded_get_heap_object_metadata_pointer(object).assumingMemoryBound(to: ClassMetadata.self)
131+
while classMetadata != metadata {
132+
_swift_embedded_invoke_heap_object_ivardestroyer(object, classMetadata)
133+
guard let superclassMetadata = classMetadata.pointee.superclassMetadata else { break }
134+
classMetadata = superclassMetadata
135+
}
136+
}
137+
119138
@_cdecl("swift_initStaticObject")
120139
public func swift_initStaticObject(metadata: Builtin.RawPointer, object: Builtin.RawPointer) -> Builtin.RawPointer {
121140
return swift_initStaticObject(metadata: UnsafeMutablePointer<ClassMetadata>(metadata), object: UnsafeMutablePointer<HeapObject>(object))._rawValue

test/embedded/classes-generic-no-stdlib.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ public func bar(t: T2) -> MyClass<T2> {
5050
// CHECK-SIL: }
5151

5252

53-
// CHECK-IR: @"$s4main7MyClassCyAA2T2VGN" = {{.*}}<{ ptr, ptr, ptr, ptr, ptr, ptr }> <{ ptr null, ptr @"$s4main7MyClassCfDAA2T2V_Tg5", ptr @"$s4main7MyClassC1txvgAA2T2V_Tg5", ptr @"$s4main7MyClassC1txvsAA2T2V_Tg5", ptr @"$s4main7MyClassC1txvMAA2T2V_Tg5", ptr @"$s4main7MyClassC1tACyxGx_tcfCAA2T2V_Tg5" }>
54-
// CHECK-IR: @"$s4main7MyClassCyAA2T1VGN" = {{.*}}<{ ptr, ptr, ptr, ptr, ptr, ptr }> <{ ptr null, ptr @"$s4main7MyClassCfDAA2T1V_Tg5", ptr @"$s4main7MyClassC1txvgAA2T1V_Tg5", ptr @"$s4main7MyClassC1txvsAA2T1V_Tg5", ptr @"$s4main7MyClassC1txvMAA2T1V_Tg5", ptr @"$s4main7MyClassC1tACyxGx_tcfCAA2T1V_Tg5" }>
53+
// CHECK-IR: @"$s4main7MyClassCyAA2T2VGN" = {{.*}}<{ ptr, ptr, ptr, ptr, ptr, ptr, ptr }> <{ ptr null, ptr @"$s4main7MyClassCfDAA2T2V_Tg5", ptr null, ptr @"$s4main7MyClassC1txvgAA2T2V_Tg5", ptr @"$s4main7MyClassC1txvsAA2T2V_Tg5", ptr @"$s4main7MyClassC1txvMAA2T2V_Tg5", ptr @"$s4main7MyClassC1tACyxGx_tcfCAA2T2V_Tg5" }>
54+
// CHECK-IR: @"$s4main7MyClassCyAA2T1VGN" = {{.*}}<{ ptr, ptr, ptr, ptr, ptr, ptr, ptr }> <{ ptr null, ptr @"$s4main7MyClassCfDAA2T1V_Tg5", ptr null, ptr @"$s4main7MyClassC1txvgAA2T1V_Tg5", ptr @"$s4main7MyClassC1txvsAA2T1V_Tg5", ptr @"$s4main7MyClassC1txvMAA2T1V_Tg5", ptr @"$s4main7MyClassC1tACyxGx_tcfCAA2T1V_Tg5" }>
5555

5656
// CHECK-IR-DAG: define {{.*}}void @"$s4main7MyClassC1txvgAA2T1V_Tg5"(ptr swiftself %0)
5757
// CHECK-IR-DAG: define {{.*}}i1 @"$s4main7MyClassC1txvgAA2T2V_Tg5"(ptr swiftself %0)

test/embedded/classes-methods-no-stdlib.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ public class MySubClass: MyClass {
1111
override func foo() { }
1212
}
1313

14-
// CHECK: @"$s4main7MyClassCN" = {{.*}}<{ ptr, ptr, ptr, ptr, ptr }> <{ ptr null, ptr @"$s4main7MyClassCfD", ptr @"$s4main7MyClassC3fooyyF", ptr @"$s4main7MyClassC3baryyF", ptr @swift_deletedMethodError }>
15-
// CHECK: @"$s4main10MySubClassCN" = {{.*}}<{ ptr, ptr, ptr, ptr, ptr }> <{ ptr @"$s4main7MyClassCN", ptr @"$s4main10MySubClassCfD", ptr @"$s4main10MySubClassC3fooyyF", ptr @"$s4main7MyClassC3baryyF", ptr @"$s4main10MySubClassCACycfC" }>
14+
// CHECK: @"$s4main7MyClassCN" = {{.*}}<{ ptr, ptr, ptr, ptr, ptr, ptr }> <{ ptr null, ptr @"$s4main7MyClassCfD", ptr null, ptr @"$s4main7MyClassC3fooyyF", ptr @"$s4main7MyClassC3baryyF", ptr @swift_deletedMethodError }>
15+
// CHECK: @"$s4main10MySubClassCN" = {{.*}}<{ ptr, ptr, ptr, ptr, ptr, ptr }> <{ ptr @"$s4main7MyClassCN", ptr @"$s4main10MySubClassCfD", ptr null, ptr @"$s4main10MySubClassC3fooyyF", ptr @"$s4main7MyClassC3baryyF", ptr @"$s4main10MySubClassCACycfC" }>
1616

1717
// CHECK: define {{.*}}void @"$s4main4test1xyAA7MyClassC_tF"(ptr %0)
1818
public func test(x: MyClass) {
1919

2020
x.foo() // goes through the vtable
2121
// CHECK: %1 = load ptr, ptr %0
22-
// CHECK: %2 = getelementptr inbounds ptr, ptr %1, i64 2
22+
// CHECK: %2 = getelementptr inbounds ptr, ptr %1, i64 3
2323
// CHECK: %3 = load ptr, ptr %2
2424
// CHECK: call swiftcc void %3(ptr swiftself %0)
2525

test/embedded/classes-no-stdlib.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
public class MyClass {}
66

7-
// CHECK-DAG: @"$s4main7MyClassCN" = {{.*}}<{ ptr, ptr, ptr }> <{ ptr null, ptr @"$s4main7MyClassCfD", ptr @"$s4main7MyClassCACycfC" }>
7+
// CHECK-DAG: @"$s4main7MyClassCN" = {{.*}}<{ ptr, ptr, ptr, ptr }> <{ ptr null, ptr @"$s4main7MyClassCfD", ptr null, ptr @"$s4main7MyClassCACycfC" }>
88
// CHECK-DAG: define {{.*}}ptr @"$s4main7MyClassCfd"
99
// CHECK-DAG: define {{.*}}void @"$s4main7MyClassCfD"
1010
// CHECK-DAG: define {{.*}}ptr @"$s4main7MyClassCACycfC"
@@ -17,7 +17,7 @@ public func foo() -> MyClass {
1717

1818
public class MySubClass: MyClass {}
1919

20-
// CHECK-DAG: @"$s4main10MySubClassCN" = {{.*}}<{ ptr, ptr, ptr }> <{ ptr @"$s4main7MyClassCN", ptr @"$s4main10MySubClassCfD", ptr @"$s4main10MySubClassCACycfC" }>
20+
// CHECK-DAG: @"$s4main10MySubClassCN" = {{.*}}<{ ptr, ptr, ptr, ptr }> <{ ptr @"$s4main7MyClassCN", ptr @"$s4main10MySubClassCfD", ptr null, ptr @"$s4main10MySubClassCACycfC" }>
2121
// CHECK-DAG: define {{.*}}ptr @"$s4main10MySubClassCACycfC"
2222
// CHECK-DAG: define {{.*}}ptr @"$s4main10MySubClassCACycfc"
2323
// CHECK-DAG: define {{.*}}ptr @"$s4main10MySubClassCfd"

test/embedded/init-throwing.swift

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// RUN: %target-run-simple-swift(-enable-experimental-feature Embedded -runtime-compatibility-version none -wmo -Xfrontend -disable-objc-interop) | %FileCheck %s
2+
3+
// REQUIRES: swift_in_compiler
4+
// REQUIRES: executable_test
5+
// REQUIRES: optimized_stdlib
6+
// REQUIRES: OS=macosx || OS=linux-gnu
7+
8+
public struct FooError: Error {}
9+
10+
public class PrintingClass {
11+
init() { print("PrintingClass.init") }
12+
deinit { print("PrintingClass.deinit") }
13+
}
14+
15+
public class Foo {
16+
var a: PrintingClass
17+
var b: PrintingClass
18+
init(shouldThrow: Bool) throws(FooError) {
19+
a = PrintingClass()
20+
if shouldThrow { throw FooError() }
21+
b = PrintingClass()
22+
}
23+
}
24+
25+
_ = try? Foo(shouldThrow: true)
26+
print("OK 1")
27+
// CHECK: PrintingClass.init
28+
// CHECK: PrintingClass.deinit
29+
// CHECK: OK 1
30+
31+
_ = try? Foo(shouldThrow: false)
32+
print("OK 2")
33+
// CHECK: PrintingClass.init
34+
// CHECK: PrintingClass.init
35+
// CHECK: PrintingClass.deinit
36+
// CHECK: PrintingClass.deinit
37+
// CHECK: OK 2
38+
39+
public class Base {
40+
var baseMember: PrintingClass
41+
init(shouldThrow: Bool) throws(FooError) {
42+
if shouldThrow { throw FooError() }
43+
baseMember = PrintingClass()
44+
}
45+
}
46+
47+
class SubClass: Base {
48+
var subClassMember: PrintingClass = PrintingClass()
49+
override init(shouldThrow: Bool) throws(FooError) {
50+
try super.init(shouldThrow: shouldThrow)
51+
}
52+
}
53+
54+
_ = try? SubClass(shouldThrow: true)
55+
print("OK 3")
56+
// CHECK: PrintingClass.init
57+
// CHECK: PrintingClass.deinit
58+
// CHECK: OK 3
59+
60+
_ = try? SubClass(shouldThrow: false)
61+
print("OK 4")
62+
// CHECK: PrintingClass.init
63+
// CHECK: PrintingClass.init
64+
// CHECK: PrintingClass.deinit
65+
// CHECK: PrintingClass.deinit
66+
// CHECK: OK 4

test/embedded/managed-buffer.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
// REQUIRES: swift_in_compiler
44
// REQUIRES: OS=macosx || OS=linux-gnu
55

6-
// CHECK: @"$s4main8MyBufferCN" = {{.*global.*}} <{ ptr @"$ss13ManagedBufferCySis5UInt8VGN", ptr @"$s4main8MyBufferCfD{{[^"]*}}", ptr @"$s4main8MyBufferC12_doNotCallMeACyt_tcfC{{[^"]*}}" }>
7-
// CHECK: @"$ss13ManagedBufferCySis5UInt8VGN" = {{.*global.*}} <{ ptr null, ptr @"$ss13ManagedBufferCfDSi_s5UInt8VTg5{{[^"]*}}", ptr @"$ss13ManagedBufferC12_doNotCallMeAByxq_Gyt_tcfCSi_s5UInt8VTg5{{[^"]*}}" }>
6+
// CHECK: @"$s4main8MyBufferCN" = {{.*global.*}} <{ ptr @"$ss13ManagedBufferCySis5UInt8VGN", ptr @"$s4main8MyBufferCfD{{[^"]*}}", ptr null, ptr @"$s4main8MyBufferC12_doNotCallMeACyt_tcfC{{[^"]*}}" }>
7+
// CHECK: @"$ss13ManagedBufferCySis5UInt8VGN" = {{.*global.*}} <{ ptr null, ptr @"$ss13ManagedBufferCfDSi_s5UInt8VTg5{{[^"]*}}", ptr null, ptr @"$ss13ManagedBufferC12_doNotCallMeAByxq_Gyt_tcfCSi_s5UInt8VTg5{{[^"]*}}" }>
88
final public class MyBuffer: ManagedBuffer<Int, UInt8> {
99
}
1010

0 commit comments

Comments
 (0)