Skip to content

Commit 5fd6e98

Browse files
authored
Merge pull request #30024 from Azoy/calling-metadata-accessor-from-swift!
Runtime: Implement wrapper function to call metadata access functions
2 parents 3aee49d + f35efee commit 5fd6e98

File tree

6 files changed

+130
-0
lines changed

6 files changed

+130
-0
lines changed

stdlib/public/SwiftShims/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ set(sources
77
KeyPath.h
88
LibcOverlayShims.h
99
LibcShims.h
10+
Metadata.h
1011
Random.h
1112
RefCount.h
1213
RuntimeShims.h

stdlib/public/SwiftShims/Metadata.h

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//===--- Metadata.h -------------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#ifndef SWIFT_STDLIB_SHIMS_METADATA_H
14+
#define SWIFT_STDLIB_SHIMS_METADATA_H
15+
16+
#include "SwiftStddef.h"
17+
#include "Visibility.h"
18+
19+
#ifndef __swift__
20+
21+
#include "swift/ABI/Metadata.h"
22+
23+
#else // ifndef __swift__
24+
25+
typedef struct {
26+
const void *type;
27+
__swift_size_t state;
28+
} MetadataResponse;
29+
30+
#endif
31+
32+
#ifdef __cplusplus
33+
namespace swift { extern "C" {
34+
#endif
35+
36+
// Shims to call a metadata accessor in Swift.
37+
SWIFT_RUNTIME_STDLIB_API
38+
MetadataResponse _swift_metadataAccessorCall(void *accessor,
39+
__swift_size_t request,
40+
const void * const *args,
41+
__swift_size_t size);
42+
#ifdef __cplusplus
43+
}} // extern "C", namespace swift
44+
#endif
45+
46+
#endif

stdlib/public/SwiftShims/module.modulemap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ module SwiftShims {
66
header "HeapObject.h"
77
header "KeyPath.h"
88
header "LibcShims.h"
9+
header "Metadata.h"
910
header "Random.h"
1011
header "RefCount.h"
1112
header "RuntimeShims.h"

stdlib/public/stubs/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ set(swift_stubs_sources
33
CommandLine.cpp
44
GlobalObjects.cpp
55
LibcShims.cpp
6+
Metadata.cpp
67
Random.cpp
78
Stubs.cpp
89
ThreadLocalStorage.cpp

stdlib/public/stubs/Metadata.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//===--- Metadata.cpp -----------------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2020 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
13+
#include "../SwiftShims/Metadata.h"
14+
#include "swift/ABI/Metadata.h"
15+
16+
// Shims to call a metadata accessor in Swift.
17+
SWIFT_RUNTIME_STDLIB_API
18+
swift::MetadataResponse
19+
swift::_swift_metadataAccessorCall(void *accessor,
20+
__swift_size_t request,
21+
const void * const *args,
22+
__swift_size_t size) {
23+
using Fn = MetadataResponse (...);
24+
auto func = reinterpret_cast<Fn *>(accessor);
25+
auto array = llvm::ArrayRef<const void *>(args, size);
26+
return MetadataAccessFunction(func)(MetadataRequest(request), array);
27+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// RUN: %target-run-simple-swift | %FileCheck %s
2+
// REQUIRES: executable_test
3+
4+
import SwiftShims
5+
6+
struct MetadataAccessFunction {
7+
let ptr: UnsafeMutableRawPointer
8+
9+
func callAsFunction(request: Int, args: [Any.Type]) -> MetadataResponse {
10+
args.withUnsafeBufferPointer {
11+
$0.baseAddress!.withMemoryRebound(
12+
to: UnsafeRawPointer?.self,
13+
capacity: args.count
14+
) {
15+
_swift_metadataAccessorCall(ptr, request, $0, args.count)
16+
}
17+
}
18+
}
19+
}
20+
21+
func callStructAccessor(
22+
for type: Any.Type,
23+
with generics: Any.Type...
24+
) -> MetadataResponse {
25+
let metadata = unsafeBitCast(type, to: UnsafeRawPointer.self)
26+
let descriptor = metadata.advanced(by: MemoryLayout<Int>.size)
27+
.load(as: UnsafeMutableRawPointer.self)
28+
let accessorLoc = descriptor.advanced(by: MemoryLayout<Int32>.size * 3)
29+
let accessor = accessorLoc.advanced(by: Int(accessorLoc.load(as: Int32.self)))
30+
31+
let accessFn = MetadataAccessFunction(ptr: accessor)
32+
return accessFn(request: 0, args: generics)
33+
}
34+
35+
let int = callStructAccessor(for: Int.self)
36+
// CHECK: Int
37+
print(unsafeBitCast(int.type!, to: Any.Type.self))
38+
// CHECK: 0
39+
print(int.state)
40+
41+
let doubleArray = callStructAccessor(for: [Int].self, with: Double.self)
42+
// CHECK: Array<Double>
43+
print(unsafeBitCast(doubleArray.type!, to: Any.Type.self))
44+
// CHECK: 0
45+
print(doubleArray.state)
46+
47+
let dictOfIntAndDoubleArray = callStructAccessor(
48+
for: [String: [Int]].self,
49+
with: Int.self, [Double].self
50+
)
51+
// CHECK: Dictionary<Int, Array<Double>>
52+
print(unsafeBitCast(dictOfIntAndDoubleArray.type!, to: Any.Type.self))
53+
// CHECK: 0
54+
print(dictOfIntAndDoubleArray.state)

0 commit comments

Comments
 (0)