mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
[embedded] Add IVarDestroyers into class metadata, add support for throws in initializers
This commit is contained in:
@@ -76,6 +76,7 @@ public:
|
||||
asImpl().noteAddressPoint();
|
||||
asImpl().addEmbeddedSuperclass(classTy);
|
||||
asImpl().addDestructorFunction();
|
||||
asImpl().addIVarDestroyer();
|
||||
addEmbeddedClassMembers(Target);
|
||||
}
|
||||
|
||||
@@ -87,6 +88,7 @@ public:
|
||||
asImpl().noteAddressPoint();
|
||||
asImpl().addSuperclass();
|
||||
asImpl().addDestructorFunction();
|
||||
asImpl().addIVarDestroyer();
|
||||
addEmbeddedClassMembers(Target);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4023,6 +4023,23 @@ namespace {
|
||||
}
|
||||
|
||||
void addIVarDestroyer() {
|
||||
if (IGM.Context.LangOpts.hasFeature(Feature::Embedded)) {
|
||||
llvm::Constant *ptr = nullptr;
|
||||
for (const SILVTable::Entry &entry : VTable->getEntries()) {
|
||||
if (entry.getMethod().kind == SILDeclRef::Kind::IVarDestroyer) {
|
||||
ptr = IGM.getAddrOfSILFunction(entry.getImplementation(), NotForDefinition);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ptr) {
|
||||
B.addSignedPointer(ptr, IGM.getOptions().PointerAuth.HeapDestructors,
|
||||
PointerAuthEntity::Special::HeapDestructor);
|
||||
} else {
|
||||
B.addNullPointer(IGM.FunctionPtrTy);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (asImpl().getFieldLayout().hasObjCImplementation())
|
||||
return;
|
||||
|
||||
|
||||
@@ -62,6 +62,20 @@ _swift_embedded_invoke_heap_object_destroy(void *object) {
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void
|
||||
_swift_embedded_invoke_heap_object_ivardestroyer(void *object, void *metadata) {
|
||||
void **ivardestroyer_location = &((void **)metadata)[2];
|
||||
#if __has_feature(ptrauth_calls)
|
||||
(*(HeapObjectDestroyer __ptrauth(0, 1, 0xbbbf) *)ivardestroyer_location)(object);
|
||||
#else
|
||||
(*(HeapObjectDestroyer *)ivardestroyer_location)(object);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void *_swift_embedded_get_heap_object_metadata_pointer(void *object) {
|
||||
return ((EmbeddedHeapObject *)object)->metadata;
|
||||
}
|
||||
|
||||
static inline void _swift_embedded_set_heap_object_metadata_pointer(void *object, void *metadata) {
|
||||
((EmbeddedHeapObject *)object)->metadata = metadata;
|
||||
}
|
||||
|
||||
@@ -17,10 +17,15 @@ import SwiftShims
|
||||
public struct ClassMetadata {
|
||||
var superclassMetadata: UnsafeMutablePointer<ClassMetadata>?
|
||||
|
||||
// There is no way to express the actual calling convention on the heap desroy
|
||||
// There is no way to express the actual calling convention on this
|
||||
// function (swiftcc with 'self') currently, so let's use UnsafeRawPointer
|
||||
// and a helper function in C (_swift_embedded_invoke_heap_object_destroy).
|
||||
var destroy: UnsafeRawPointer
|
||||
|
||||
// There is no way to express the actual calling convention on this
|
||||
// function (swiftcc with 'self') currently, so let's use UnsafeRawPointer
|
||||
// and a helper function in C (_swift_embedded_invoke_heap_object_ivardestroyer).
|
||||
var ivarDestroyer: UnsafeRawPointer
|
||||
}
|
||||
|
||||
public struct HeapObject {
|
||||
@@ -116,6 +121,20 @@ func swift_deallocClassInstance(object: UnsafeMutablePointer<HeapObject>, alloca
|
||||
free(object._rawValue)
|
||||
}
|
||||
|
||||
@_cdecl("swift_deallocPartialClassInstance")
|
||||
public func swift_deallocPartialClassInstance(object: Builtin.RawPointer, metadata: Builtin.RawPointer, allocatedSize: Int, allocatedAlignMask: Int) {
|
||||
swift_deallocPartialClassInstance(object: UnsafeMutablePointer<HeapObject>(object), metadata: UnsafeMutablePointer<ClassMetadata>(metadata), allocatedSize: allocatedSize, allocatedAlignMask: allocatedAlignMask)
|
||||
}
|
||||
|
||||
func swift_deallocPartialClassInstance(object: UnsafeMutablePointer<HeapObject>, metadata: UnsafeMutablePointer<ClassMetadata>, allocatedSize: Int, allocatedAlignMask: Int) {
|
||||
var classMetadata = _swift_embedded_get_heap_object_metadata_pointer(object).assumingMemoryBound(to: ClassMetadata.self)
|
||||
while classMetadata != metadata {
|
||||
_swift_embedded_invoke_heap_object_ivardestroyer(object, classMetadata)
|
||||
guard let superclassMetadata = classMetadata.pointee.superclassMetadata else { break }
|
||||
classMetadata = superclassMetadata
|
||||
}
|
||||
}
|
||||
|
||||
@_cdecl("swift_initStaticObject")
|
||||
public func swift_initStaticObject(metadata: Builtin.RawPointer, object: Builtin.RawPointer) -> Builtin.RawPointer {
|
||||
return swift_initStaticObject(metadata: UnsafeMutablePointer<ClassMetadata>(metadata), object: UnsafeMutablePointer<HeapObject>(object))._rawValue
|
||||
|
||||
@@ -50,8 +50,8 @@ public func bar(t: T2) -> MyClass<T2> {
|
||||
// CHECK-SIL: }
|
||||
|
||||
|
||||
// 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" }>
|
||||
// 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" }>
|
||||
// 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" }>
|
||||
// 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" }>
|
||||
|
||||
// CHECK-IR-DAG: define {{.*}}void @"$s4main7MyClassC1txvgAA2T1V_Tg5"(ptr swiftself %0)
|
||||
// CHECK-IR-DAG: define {{.*}}i1 @"$s4main7MyClassC1txvgAA2T2V_Tg5"(ptr swiftself %0)
|
||||
|
||||
@@ -11,15 +11,15 @@ public class MySubClass: MyClass {
|
||||
override func foo() { }
|
||||
}
|
||||
|
||||
// CHECK: @"$s4main7MyClassCN" = {{.*}}<{ ptr, ptr, ptr, ptr, ptr }> <{ ptr null, ptr @"$s4main7MyClassCfD", ptr @"$s4main7MyClassC3fooyyF", ptr @"$s4main7MyClassC3baryyF", ptr @swift_deletedMethodError }>
|
||||
// CHECK: @"$s4main10MySubClassCN" = {{.*}}<{ ptr, ptr, ptr, ptr, ptr }> <{ ptr @"$s4main7MyClassCN", ptr @"$s4main10MySubClassCfD", ptr @"$s4main10MySubClassC3fooyyF", ptr @"$s4main7MyClassC3baryyF", ptr @"$s4main10MySubClassCACycfC" }>
|
||||
// CHECK: @"$s4main7MyClassCN" = {{.*}}<{ ptr, ptr, ptr, ptr, ptr, ptr }> <{ ptr null, ptr @"$s4main7MyClassCfD", ptr null, ptr @"$s4main7MyClassC3fooyyF", ptr @"$s4main7MyClassC3baryyF", ptr @swift_deletedMethodError }>
|
||||
// CHECK: @"$s4main10MySubClassCN" = {{.*}}<{ ptr, ptr, ptr, ptr, ptr, ptr }> <{ ptr @"$s4main7MyClassCN", ptr @"$s4main10MySubClassCfD", ptr null, ptr @"$s4main10MySubClassC3fooyyF", ptr @"$s4main7MyClassC3baryyF", ptr @"$s4main10MySubClassCACycfC" }>
|
||||
|
||||
// CHECK: define {{.*}}void @"$s4main4test1xyAA7MyClassC_tF"(ptr %0)
|
||||
public func test(x: MyClass) {
|
||||
|
||||
x.foo() // goes through the vtable
|
||||
// CHECK: %1 = load ptr, ptr %0
|
||||
// CHECK: %2 = getelementptr inbounds ptr, ptr %1, i64 2
|
||||
// CHECK: %2 = getelementptr inbounds ptr, ptr %1, i64 3
|
||||
// CHECK: %3 = load ptr, ptr %2
|
||||
// CHECK: call swiftcc void %3(ptr swiftself %0)
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
public class MyClass {}
|
||||
|
||||
// CHECK-DAG: @"$s4main7MyClassCN" = {{.*}}<{ ptr, ptr, ptr }> <{ ptr null, ptr @"$s4main7MyClassCfD", ptr @"$s4main7MyClassCACycfC" }>
|
||||
// CHECK-DAG: @"$s4main7MyClassCN" = {{.*}}<{ ptr, ptr, ptr, ptr }> <{ ptr null, ptr @"$s4main7MyClassCfD", ptr null, ptr @"$s4main7MyClassCACycfC" }>
|
||||
// CHECK-DAG: define {{.*}}ptr @"$s4main7MyClassCfd"
|
||||
// CHECK-DAG: define {{.*}}void @"$s4main7MyClassCfD"
|
||||
// CHECK-DAG: define {{.*}}ptr @"$s4main7MyClassCACycfC"
|
||||
@@ -17,7 +17,7 @@ public func foo() -> MyClass {
|
||||
|
||||
public class MySubClass: MyClass {}
|
||||
|
||||
// CHECK-DAG: @"$s4main10MySubClassCN" = {{.*}}<{ ptr, ptr, ptr }> <{ ptr @"$s4main7MyClassCN", ptr @"$s4main10MySubClassCfD", ptr @"$s4main10MySubClassCACycfC" }>
|
||||
// CHECK-DAG: @"$s4main10MySubClassCN" = {{.*}}<{ ptr, ptr, ptr, ptr }> <{ ptr @"$s4main7MyClassCN", ptr @"$s4main10MySubClassCfD", ptr null, ptr @"$s4main10MySubClassCACycfC" }>
|
||||
// CHECK-DAG: define {{.*}}ptr @"$s4main10MySubClassCACycfC"
|
||||
// CHECK-DAG: define {{.*}}ptr @"$s4main10MySubClassCACycfc"
|
||||
// CHECK-DAG: define {{.*}}ptr @"$s4main10MySubClassCfd"
|
||||
|
||||
66
test/embedded/init-throwing.swift
Normal file
66
test/embedded/init-throwing.swift
Normal file
@@ -0,0 +1,66 @@
|
||||
// RUN: %target-run-simple-swift(-enable-experimental-feature Embedded -runtime-compatibility-version none -wmo -Xfrontend -disable-objc-interop) | %FileCheck %s
|
||||
|
||||
// REQUIRES: swift_in_compiler
|
||||
// REQUIRES: executable_test
|
||||
// REQUIRES: optimized_stdlib
|
||||
// REQUIRES: OS=macosx || OS=linux-gnu
|
||||
|
||||
public struct FooError: Error {}
|
||||
|
||||
public class PrintingClass {
|
||||
init() { print("PrintingClass.init") }
|
||||
deinit { print("PrintingClass.deinit") }
|
||||
}
|
||||
|
||||
public class Foo {
|
||||
var a: PrintingClass
|
||||
var b: PrintingClass
|
||||
init(shouldThrow: Bool) throws(FooError) {
|
||||
a = PrintingClass()
|
||||
if shouldThrow { throw FooError() }
|
||||
b = PrintingClass()
|
||||
}
|
||||
}
|
||||
|
||||
_ = try? Foo(shouldThrow: true)
|
||||
print("OK 1")
|
||||
// CHECK: PrintingClass.init
|
||||
// CHECK: PrintingClass.deinit
|
||||
// CHECK: OK 1
|
||||
|
||||
_ = try? Foo(shouldThrow: false)
|
||||
print("OK 2")
|
||||
// CHECK: PrintingClass.init
|
||||
// CHECK: PrintingClass.init
|
||||
// CHECK: PrintingClass.deinit
|
||||
// CHECK: PrintingClass.deinit
|
||||
// CHECK: OK 2
|
||||
|
||||
public class Base {
|
||||
var baseMember: PrintingClass
|
||||
init(shouldThrow: Bool) throws(FooError) {
|
||||
if shouldThrow { throw FooError() }
|
||||
baseMember = PrintingClass()
|
||||
}
|
||||
}
|
||||
|
||||
class SubClass: Base {
|
||||
var subClassMember: PrintingClass = PrintingClass()
|
||||
override init(shouldThrow: Bool) throws(FooError) {
|
||||
try super.init(shouldThrow: shouldThrow)
|
||||
}
|
||||
}
|
||||
|
||||
_ = try? SubClass(shouldThrow: true)
|
||||
print("OK 3")
|
||||
// CHECK: PrintingClass.init
|
||||
// CHECK: PrintingClass.deinit
|
||||
// CHECK: OK 3
|
||||
|
||||
_ = try? SubClass(shouldThrow: false)
|
||||
print("OK 4")
|
||||
// CHECK: PrintingClass.init
|
||||
// CHECK: PrintingClass.init
|
||||
// CHECK: PrintingClass.deinit
|
||||
// CHECK: PrintingClass.deinit
|
||||
// CHECK: OK 4
|
||||
@@ -3,8 +3,8 @@
|
||||
// REQUIRES: swift_in_compiler
|
||||
// REQUIRES: OS=macosx || OS=linux-gnu
|
||||
|
||||
// CHECK: @"$s4main8MyBufferCN" = {{.*global.*}} <{ ptr @"$ss13ManagedBufferCySis5UInt8VGN", ptr @"$s4main8MyBufferCfD{{[^"]*}}", ptr @"$s4main8MyBufferC12_doNotCallMeACyt_tcfC{{[^"]*}}" }>
|
||||
// CHECK: @"$ss13ManagedBufferCySis5UInt8VGN" = {{.*global.*}} <{ ptr null, ptr @"$ss13ManagedBufferCfDSi_s5UInt8VTg5{{[^"]*}}", ptr @"$ss13ManagedBufferC12_doNotCallMeAByxq_Gyt_tcfCSi_s5UInt8VTg5{{[^"]*}}" }>
|
||||
// CHECK: @"$s4main8MyBufferCN" = {{.*global.*}} <{ ptr @"$ss13ManagedBufferCySis5UInt8VGN", ptr @"$s4main8MyBufferCfD{{[^"]*}}", ptr null, ptr @"$s4main8MyBufferC12_doNotCallMeACyt_tcfC{{[^"]*}}" }>
|
||||
// CHECK: @"$ss13ManagedBufferCySis5UInt8VGN" = {{.*global.*}} <{ ptr null, ptr @"$ss13ManagedBufferCfDSi_s5UInt8VTg5{{[^"]*}}", ptr null, ptr @"$ss13ManagedBufferC12_doNotCallMeAByxq_Gyt_tcfCSi_s5UInt8VTg5{{[^"]*}}" }>
|
||||
final public class MyBuffer: ManagedBuffer<Int, UInt8> {
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user