Skip to content

Commit eda5ead

Browse files
committed
Start outline storage support: Add swift_allocBox/deallocBox
Code using the outline heap storage path will crash and burn because support is incomplete. But at least inline storage existential inhabitants should compile and run.
1 parent 93bc84e commit eda5ead

File tree

3 files changed

+102
-0
lines changed

3 files changed

+102
-0
lines changed

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

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,51 @@ static inline void _swift_embedded_set_heap_object_metadata_pointer(void *object
8383
((EmbeddedHeapObject *)object)->metadata = metadata;
8484
}
8585

86+
typedef struct {
87+
void *initializeBufferWithCopyOfBufferFn;
88+
#if __has_feature(ptrauth_calls)
89+
void (* __ptrauth(0, 1, 0x04f8) destroyFn)(void *, void*);
90+
#else
91+
void (*destroyFn)(void *, void*);
92+
#endif
93+
#if __has_feature(ptrauth_calls)
94+
void* (* __ptrauth(0, 1, 0xe3ba) initializeWithCopyFn)(void*, void*, void*);
95+
#else
96+
void* (*initializeWithCopyFn)(void*, void*, void*);
97+
#endif
98+
void *assignWithCopyFn;
99+
void *initializeWithTakeFn;
100+
void *assignWithTakeFn;
101+
void *getEnumTagSinglePayloadFn;
102+
void *storeEnumTagSinglePayload;
103+
__swift_size_t size;
104+
__swift_size_t stride;
105+
unsigned flags;
106+
} EmbeddedValueWitnessTable;
107+
108+
typedef struct {
109+
#if __has_feature(ptrauth_calls)
110+
EmbeddedValueWitnessTable * __ptrauth(2, 1, 0x2e3f) vwt;
111+
#else
112+
EmbeddedValueWitnessTable *vwt;
113+
#endif
114+
} EmbeddedMetaDataPrefix;
115+
116+
static inline __swift_size_t _swift_embedded_metadata_get_size(void *metadata) {
117+
EmbeddedMetaDataPrefix *fullmeta = (EmbeddedMetaDataPrefix*)&((void **)metadata)[-1];
118+
return fullmeta->vwt->size;
119+
}
120+
121+
static inline __swift_size_t _swift_embedded_metadata_get_align_mask(void *metadata) {
122+
EmbeddedMetaDataPrefix *fullmeta = (EmbeddedMetaDataPrefix*)&((void **)metadata)[-1];
123+
124+
unsigned flags = fullmeta->vwt->flags;
125+
unsigned embeddedValueWitnessTableFlagsMask = 0xFF;
126+
127+
return flags & embeddedValueWitnessTableFlagsMask;
128+
}
129+
130+
86131
#ifdef __cplusplus
87132
} // extern "C"
88133
#endif

stdlib/public/core/EmbeddedRuntime.swift

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,34 @@ public func swift_allocEmptyBox() -> Builtin.RawPointer {
262262
}
263263

264264

265+
@_silgen_name("swift_allocBox")
266+
public func swift_allocBox(metadata: Builtin.RawPointer) -> (Builtin.RawPointer, Builtin.RawPointer) {
267+
let alignMask = Int(unsafe _swift_embedded_metadata_get_align_mask(UnsafeMutableRawPointer(metadata)))
268+
let size = Int(unsafe _swift_embedded_metadata_get_size(UnsafeMutableRawPointer(metadata)))
269+
let headerSize = unsafe MemoryLayout<Int>.size + MemoryLayout<UnsafeRawPointer>.size
270+
let headerAlignMask = unsafe MemoryLayout<UnsafeRawPointer>.alignment - 1
271+
let startOfBoxedValue = ((headerSize + alignMask) & ~alignMask)
272+
let requiredSize: Int = startOfBoxedValue + size
273+
let requiredAlignmentMask: Int = alignMask | headerAlignMask
274+
275+
let p = unsafe swift_slowAlloc(requiredSize, requiredAlignmentMask)!
276+
let object = unsafe p.assumingMemoryBound(to: HeapObject.self)
277+
278+
unsafe _swift_embedded_set_heap_object_metadata_pointer(object, UnsafeMutableRawPointer(metadata))
279+
unsafe object.pointee.refcount = 1
280+
281+
let boxedValueAddr = unsafe UnsafeMutableRawPointer(p).advanced(by: startOfBoxedValue)
282+
283+
return (object._rawValue, boxedValueAddr._rawValue)
284+
}
285+
286+
@_cdecl("swift_deallocBox")
287+
public func swift_deallocBox(object: Builtin.RawPointer) {
288+
unsafe free(UnsafeMutableRawPointer(object))
289+
}
290+
291+
292+
265293
/// Refcounting
266294

267295
func isValidPointerForNativeRetain(object: Builtin.RawPointer) -> Bool {

test/embedded/existential.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,33 @@ func test2(_ p: any Derived) {
117117
p.b()
118118
}
119119

120+
121+
protocol ValuePrinter {
122+
func printValue()
123+
}
124+
protocol WithAssoc {
125+
associatedtype Assoc : ValuePrinter
126+
func a() -> Assoc
127+
}
128+
129+
extension Int : ValuePrinter {
130+
func printValue() {
131+
print("my value: \(self)")
132+
}
133+
}
134+
135+
struct ConformWithAssoc : WithAssoc {
136+
var x = 1
137+
func a() -> Int {
138+
return x
139+
}
140+
}
141+
142+
func test3(_ p: any WithAssoc) {
143+
let x = p.a()
144+
x.printValue()
145+
}
146+
120147
@main
121148
struct Main {
122149
static func main() {
@@ -131,9 +158,11 @@ struct Main {
131158
// OUTPUT: a MyEnum
132159
// OUTPUT: 5
133160
// OUTPUT: b MyEnum
161+
// OUTPUT: my value: 1
134162
test2(Implementor())
135163
test2(5)
136164
test2(MyStruct())
137165
test2(MyEnum.b(5))
166+
test3(ConformWithAssoc())
138167
}
139168
}

0 commit comments

Comments
 (0)