Skip to content

Commit 3af8388

Browse files
committed
[embedded] Support closures with captures and promoting locals to refcounted heap objects
1 parent 0f7eb45 commit 3af8388

File tree

4 files changed

+59
-0
lines changed

4 files changed

+59
-0
lines changed

lib/Frontend/CompilerInvocation.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3118,6 +3118,8 @@ bool CompilerInvocation::parseArgs(
31183118
if (LangOpts.hasFeature(Feature::Embedded)) {
31193119
IRGenOpts.InternalizeAtLink = true;
31203120
IRGenOpts.DisableLegacyTypeInfo = true;
3121+
IRGenOpts.ReflectionMetadata = ReflectionMetadataMode::None;
3122+
IRGenOpts.EnableReflectionNames = false;
31213123
SILOpts.CMOMode = CrossModuleOptimizationMode::Everything;
31223124
SILOpts.EmbeddedSwift = true;
31233125
}

lib/IRGen/GenHeap.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,22 @@ static llvm::Constant *buildPrivateMetadata(IRGenModule &IGM,
499499
MetadataKind kind) {
500500
// Build the fields of the private metadata.
501501
ConstantInitBuilder builder(IGM);
502+
503+
// In embedded Swift, heap objects have a different, simple(r) layout:
504+
// superclass pointer + destructor.
505+
if (IGM.Context.LangOpts.hasFeature(Feature::Embedded)) {
506+
auto fields = builder.beginStruct();
507+
fields.addNullPointer(IGM.Int8PtrTy);
508+
fields.addSignedPointer(dtorFn,
509+
IGM.getOptions().PointerAuth.HeapDestructors,
510+
PointerAuthEntity::Special::HeapDestructor);
511+
512+
llvm::GlobalVariable *var = fields.finishAndCreateGlobal(
513+
"metadata", IGM.getPointerAlignment(), /*constant*/ true,
514+
llvm::GlobalVariable::PrivateLinkage);
515+
return var;
516+
}
517+
502518
auto fields = builder.beginStruct(IGM.FullBoxMetadataStructTy);
503519

504520
fields.addSignedPointer(dtorFn, IGM.getOptions().PointerAuth.HeapDestructors,

stdlib/public/core/EmbeddedRuntime.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ public func swift_allocObject(metadata: UnsafeMutablePointer<ClassMetadata>, req
7171
return object
7272
}
7373

74+
@_silgen_name("swift_deallocObject")
75+
public func swift_deallocObject(object: UnsafeMutablePointer<HeapObject>, allocatedSize: Int, allocatedAlignMask: Int) {
76+
free(object)
77+
}
78+
7479
@_silgen_name("swift_deallocClassInstance")
7580
public func swift_deallocClassInstance(object: UnsafeMutablePointer<HeapObject>, allocatedSize: Int, allocatedAlignMask: Int) {
7681
if (object.pointee.refcount & HeapObject.doNotFreeBit) != 0 {

test/embedded/closures-heap.swift

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend %s %S/Inputs/print.swift -enable-experimental-feature Embedded -c -o %t/main.o
3+
// RUN: %target-clang %t/main.o -o %t/a.out -dead_strip
4+
// RUN: %target-run %t/a.out | %FileCheck %s
5+
6+
// REQUIRES: executable_test
7+
// REQUIRES: optimized_stdlib
8+
// REQUIRES: VENDOR=apple
9+
// REQUIRES: OS=macosx
10+
11+
public class MyClass {
12+
var handler: (()->())? = nil
13+
func foo() {
14+
handler?()
15+
}
16+
deinit { print("deinit") }
17+
}
18+
19+
@main
20+
struct Main {
21+
static var o: MyClass? = nil
22+
23+
static func main() {
24+
o = MyClass()
25+
o!.handler = { print("no captures") }
26+
o!.foo() // CHECK: no captures
27+
o = nil // CHECK: deinit
28+
29+
var local = 42
30+
o = MyClass()
31+
o!.handler = { print("capture local"); local += 1 }
32+
o!.foo() // CHECK: capture local
33+
print(local == 43 ? "43" : "???") // CHECK: 43
34+
o = nil // CHECK: deinit
35+
}
36+
}

0 commit comments

Comments
 (0)