mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
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.
This commit is contained in:
@@ -83,6 +83,51 @@ static inline void _swift_embedded_set_heap_object_metadata_pointer(void *object
|
||||
((EmbeddedHeapObject *)object)->metadata = metadata;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
void *initializeBufferWithCopyOfBufferFn;
|
||||
#if __has_feature(ptrauth_calls)
|
||||
void (* __ptrauth(0, 1, 0x04f8) destroyFn)(void *, void*);
|
||||
#else
|
||||
void (*destroyFn)(void *, void*);
|
||||
#endif
|
||||
#if __has_feature(ptrauth_calls)
|
||||
void* (* __ptrauth(0, 1, 0xe3ba) initializeWithCopyFn)(void*, void*, void*);
|
||||
#else
|
||||
void* (*initializeWithCopyFn)(void*, void*, void*);
|
||||
#endif
|
||||
void *assignWithCopyFn;
|
||||
void *initializeWithTakeFn;
|
||||
void *assignWithTakeFn;
|
||||
void *getEnumTagSinglePayloadFn;
|
||||
void *storeEnumTagSinglePayload;
|
||||
__swift_size_t size;
|
||||
__swift_size_t stride;
|
||||
unsigned flags;
|
||||
} EmbeddedValueWitnessTable;
|
||||
|
||||
typedef struct {
|
||||
#if __has_feature(ptrauth_calls)
|
||||
EmbeddedValueWitnessTable * __ptrauth(2, 1, 0x2e3f) vwt;
|
||||
#else
|
||||
EmbeddedValueWitnessTable *vwt;
|
||||
#endif
|
||||
} EmbeddedMetaDataPrefix;
|
||||
|
||||
static inline __swift_size_t _swift_embedded_metadata_get_size(void *metadata) {
|
||||
EmbeddedMetaDataPrefix *fullmeta = (EmbeddedMetaDataPrefix*)&((void **)metadata)[-1];
|
||||
return fullmeta->vwt->size;
|
||||
}
|
||||
|
||||
static inline __swift_size_t _swift_embedded_metadata_get_align_mask(void *metadata) {
|
||||
EmbeddedMetaDataPrefix *fullmeta = (EmbeddedMetaDataPrefix*)&((void **)metadata)[-1];
|
||||
|
||||
unsigned flags = fullmeta->vwt->flags;
|
||||
unsigned embeddedValueWitnessTableFlagsMask = 0xFF;
|
||||
|
||||
return flags & embeddedValueWitnessTableFlagsMask;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
@@ -262,6 +262,34 @@ public func swift_allocEmptyBox() -> Builtin.RawPointer {
|
||||
}
|
||||
|
||||
|
||||
@_silgen_name("swift_allocBox")
|
||||
public func swift_allocBox(metadata: Builtin.RawPointer) -> (Builtin.RawPointer, Builtin.RawPointer) {
|
||||
let alignMask = Int(unsafe _swift_embedded_metadata_get_align_mask(UnsafeMutableRawPointer(metadata)))
|
||||
let size = Int(unsafe _swift_embedded_metadata_get_size(UnsafeMutableRawPointer(metadata)))
|
||||
let headerSize = unsafe MemoryLayout<Int>.size + MemoryLayout<UnsafeRawPointer>.size
|
||||
let headerAlignMask = unsafe MemoryLayout<UnsafeRawPointer>.alignment - 1
|
||||
let startOfBoxedValue = ((headerSize + alignMask) & ~alignMask)
|
||||
let requiredSize: Int = startOfBoxedValue + size
|
||||
let requiredAlignmentMask: Int = alignMask | headerAlignMask
|
||||
|
||||
let p = unsafe swift_slowAlloc(requiredSize, requiredAlignmentMask)!
|
||||
let object = unsafe p.assumingMemoryBound(to: HeapObject.self)
|
||||
|
||||
unsafe _swift_embedded_set_heap_object_metadata_pointer(object, UnsafeMutableRawPointer(metadata))
|
||||
unsafe object.pointee.refcount = 1
|
||||
|
||||
let boxedValueAddr = unsafe UnsafeMutableRawPointer(p).advanced(by: startOfBoxedValue)
|
||||
|
||||
return (object._rawValue, boxedValueAddr._rawValue)
|
||||
}
|
||||
|
||||
@_cdecl("swift_deallocBox")
|
||||
public func swift_deallocBox(object: Builtin.RawPointer) {
|
||||
unsafe free(UnsafeMutableRawPointer(object))
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// Refcounting
|
||||
|
||||
func isValidPointerForNativeRetain(object: Builtin.RawPointer) -> Bool {
|
||||
|
||||
@@ -117,6 +117,33 @@ func test2(_ p: any Derived) {
|
||||
p.b()
|
||||
}
|
||||
|
||||
|
||||
protocol ValuePrinter {
|
||||
func printValue()
|
||||
}
|
||||
protocol WithAssoc {
|
||||
associatedtype Assoc : ValuePrinter
|
||||
func a() -> Assoc
|
||||
}
|
||||
|
||||
extension Int : ValuePrinter {
|
||||
func printValue() {
|
||||
print("my value: \(self)")
|
||||
}
|
||||
}
|
||||
|
||||
struct ConformWithAssoc : WithAssoc {
|
||||
var x = 1
|
||||
func a() -> Int {
|
||||
return x
|
||||
}
|
||||
}
|
||||
|
||||
func test3(_ p: any WithAssoc) {
|
||||
let x = p.a()
|
||||
x.printValue()
|
||||
}
|
||||
|
||||
@main
|
||||
struct Main {
|
||||
static func main() {
|
||||
@@ -131,9 +158,11 @@ struct Main {
|
||||
// OUTPUT: a MyEnum
|
||||
// OUTPUT: 5
|
||||
// OUTPUT: b MyEnum
|
||||
// OUTPUT: my value: 1
|
||||
test2(Implementor())
|
||||
test2(5)
|
||||
test2(MyStruct())
|
||||
test2(MyEnum.b(5))
|
||||
test3(ConformWithAssoc())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user