Skip to content

Commit e82a0b9

Browse files
committed
Runtime: Implement wrapper function for metadata access functions
1 parent b78ed53 commit e82a0b9

File tree

3 files changed

+68
-0
lines changed

3 files changed

+68
-0
lines changed

include/swift/Runtime/Metadata.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,13 @@ void swift_enableDynamicReplacementScope(const DynamicReplacementScope *scope);
843843
SWIFT_RUNTIME_EXPORT
844844
void swift_disableDynamicReplacementScope(const DynamicReplacementScope *scope);
845845

846+
// Shim to allow Swift to call metadata accessors.
847+
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
848+
MetadataResponse _swift_metadataAccessorCall(void *accessor,
849+
MetadataRequest request,
850+
const void * const *args,
851+
size_t count);
852+
846853
#pragma clang diagnostic pop
847854

848855
} // end namespace swift

stdlib/public/runtime/Metadata.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5591,6 +5591,17 @@ SWIFT_RUNTIME_STDLIB_SPI
55915591
const HeapObject *swift_getKeyPathImpl(const void *pattern,
55925592
const void *arguments);
55935593

5594+
// Shims to call a metadata accessor in Swift.
5595+
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
5596+
MetadataResponse _swift_metadataAccessorCall(void *accessor,
5597+
MetadataRequest request,
5598+
const void * const *args,
5599+
size_t count) {
5600+
using Fn = MetadataResponse (...);
5601+
auto func = reinterpret_cast<Fn *>(accessor);
5602+
return MetadataAccessFunction(func)(request, llvm::makeArrayRef(args, count));
5603+
}
5604+
55945605
#define OVERRIDE_KEYPATH COMPATIBILITY_OVERRIDE
55955606
#define OVERRIDE_WITNESSTABLE COMPATIBILITY_OVERRIDE
55965607
#include "CompatibilityOverride.def"
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// RUN: %target-run-simple-swift | %FileCheck %s
2+
// REQUIRES: executable_test
3+
4+
@_silgen_name("_swift_metadataAccessorCall")
5+
func _metadataAccessorCall(
6+
fn: UnsafeRawPointer,
7+
request: UInt,
8+
args: UnsafePointer<Any.Type>?,
9+
count: Int
10+
) -> MetadataResponse
11+
12+
struct MetadataResponse {
13+
let type: Any.Type
14+
15+
let state: UInt8
16+
}
17+
18+
struct MetadataAccessFunction {
19+
let ptr: UnsafeRawPointer
20+
21+
func callAsFunction(request: UInt, args: [Any.Type]) -> MetadataResponse {
22+
args.withUnsafeBufferPointer {
23+
_metadataAccessorCall(
24+
fn: ptr,
25+
request: request,
26+
args: $0.baseAddress!,
27+
count: $0.count
28+
)
29+
}
30+
}
31+
}
32+
33+
func callStructAccessor(for type: Any.Type, with generics: Any.Type...) {
34+
let metadata = unsafeBitCast(type, to: UnsafeRawPointer.self)
35+
let descriptor = metadata.advanced(by: 8).load(as: UnsafeRawPointer.self)
36+
let accessorLoc = descriptor.advanced(by: 12)
37+
let accessor = accessorLoc.advanced(by: Int(accessorLoc.load(as: Int32.self)))
38+
39+
let accessFn = MetadataAccessFunction(ptr: accessor)
40+
print(accessFn(request: 0, args: generics))
41+
}
42+
43+
// CHECK: MetadataResponse(type: Swift.Int, state: 0)
44+
callStructAccessor(for: Int.self)
45+
46+
// CHECK: MetadataResponse(type: Swift.Array<Swift.Double>, state: 0)
47+
callStructAccessor(for: [Int].self, with: Double.self)
48+
49+
// CHECK: MetadataResponse(type: Swift.Dictionary<Swift.Int, Swift.Array<Swift.Double>>, state: 0)
50+
callStructAccessor(for: [String: [Int]].self, with: Int.self, [Double].self)

0 commit comments

Comments
 (0)