Skip to content

Commit 458eccc

Browse files
committed
[LibSwiftScan] Add entry-points for querying protocol conformances from the static mirror
This commit adds new entry-points to `libSwiftScan` that operate on the new BinaryScanningTool, which reads out Swift type information from object files, starting with a query of all protocol conformances.
1 parent 925ad7b commit 458eccc

File tree

16 files changed

+492
-57
lines changed

16 files changed

+492
-57
lines changed
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
//===--- BinaryScan.h - C API for Swift Binary Scanning ---*- C -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 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+
// This C API is primarily intended to serve as a "static mirror" library
14+
// for querying Swift type information from binary object files.
15+
//
16+
//===----------------------------------------------------------------------===//
17+
18+
#include "DependencyScanMacros.h"
19+
#include "CommonString.h"
20+
21+
#ifndef SWIFT_C_BINARY_SCAN_H
22+
#define SWIFT_C_BINARY_SCAN_H
23+
24+
SWIFTSCAN_BEGIN_DECLS
25+
26+
//=== Public Binary Scanner Data Types ------------------------------------===//
27+
28+
/// Container of the configuration state for binary static mirror scanning
29+
/// instance
30+
typedef void *swiftscan_static_mirror_t;
31+
32+
/// Opaque container to a conformance type info of a given protocol conformance.
33+
typedef struct swiftscan_conformance_info_s
34+
*swiftscan_static_mirror_conformance_info_t;
35+
36+
typedef struct {
37+
swiftscan_static_mirror_conformance_info_t *conformances;
38+
size_t count;
39+
} swiftscan_static_mirror_conformances_set_t;
40+
41+
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
42+
swiftscan_static_mirror_conformance_info_get_type_name(
43+
swiftscan_static_mirror_conformance_info_t);
44+
45+
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
46+
swiftscan_static_mirror_conformance_info_get_protocol_name(
47+
swiftscan_static_mirror_conformance_info_t);
48+
49+
SWIFTSCAN_PUBLIC swiftscan_string_ref_t
50+
swiftscan_static_mirror_conformance_info_get_mangled_type_name(
51+
swiftscan_static_mirror_conformance_info_t);
52+
53+
SWIFTSCAN_PUBLIC void
54+
swiftscan_static_mirror_conformance_info_dispose(
55+
swiftscan_static_mirror_conformance_info_t);
56+
57+
/// Create an \c swiftscan_static_mirror_t instance.
58+
/// The returned \c swiftscan_static_mirror_t is owned by the caller and must be
59+
/// disposed of using \c swiftscan_static_mirror_dispose .
60+
SWIFTSCAN_PUBLIC swiftscan_static_mirror_t
61+
swiftscan_static_mirror_create(int, const char **, const char *);
62+
63+
SWIFTSCAN_PUBLIC void
64+
swiftscan_static_mirror_dispose(swiftscan_static_mirror_t);
65+
66+
/// Identify and collect all types conforming to any of the protocol names
67+
/// specified as arguments
68+
SWIFTSCAN_PUBLIC swiftscan_static_mirror_conformances_set_t *
69+
swiftscan_static_mirror_conformances_set_create(
70+
swiftscan_static_mirror_t, int, const char **);
71+
72+
SWIFTSCAN_PUBLIC void swiftscan_static_mirror_conformances_set_dispose(
73+
swiftscan_static_mirror_conformances_set_t *);
74+
75+
SWIFTSCAN_END_DECLS
76+
77+
#endif // SWIFT_C_BINARY_SCAN_H
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//===--- CommonString.h - C API for Swift Dependency Scanning ---*- C -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 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_C_LIB_SWIFT_SCAN_STRING_H
14+
#define SWIFT_C_LIB_SWIFT_SCAN_STRING_H
15+
16+
#include <stdbool.h>
17+
#include <stddef.h>
18+
#include <stdint.h>
19+
20+
SWIFTSCAN_BEGIN_DECLS
21+
22+
//=== String Data Types used by LibSwift Scan ----------------------------===//
23+
24+
/**
25+
* A character string used to pass around dependency scan result metadata.
26+
* Lifetime of the string is strictly tied to the object whose field it
27+
* represents. When the owning object is released, string memory is freed.
28+
*/
29+
typedef struct {
30+
const void *data;
31+
size_t length;
32+
} swiftscan_string_ref_t;
33+
34+
typedef struct {
35+
swiftscan_string_ref_t *strings;
36+
size_t count;
37+
} swiftscan_string_set_t;
38+
39+
SWIFTSCAN_END_DECLS
40+
41+
#endif // SWIFT_C_DEPENDENCY_SCAN_H

include/swift-c/DependencyScan/DependencyScan.h

Lines changed: 6 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -15,38 +15,15 @@
1515
//
1616
//===----------------------------------------------------------------------===//
1717

18-
#ifndef SWIFT_C_DEPENDENCY_SCAN_H
19-
#define SWIFT_C_DEPENDENCY_SCAN_H
20-
2118
#include "DependencyScanMacros.h"
22-
#include <stdbool.h>
23-
#include <stddef.h>
24-
#include <stdint.h>
19+
#include "CommonString.h"
2520

26-
/// The version constants for the SwiftDependencyScan C API.
27-
/// SWIFTSCAN_VERSION_MINOR should increase when there are API additions.
28-
/// SWIFTSCAN_VERSION_MAJOR is intended for "major" source/ABI breaking changes.
29-
#define SWIFTSCAN_VERSION_MAJOR 0
30-
#define SWIFTSCAN_VERSION_MINOR 2
21+
#ifndef SWIFT_C_DEPENDENCY_SCAN_H
22+
#define SWIFT_C_DEPENDENCY_SCAN_H
3123

3224
SWIFTSCAN_BEGIN_DECLS
3325

34-
//=== Public Scanner Data Types -------------------------------------------===//
35-
36-
/**
37-
* A character string used to pass around dependency scan result metadata.
38-
* Lifetime of the string is strictly tied to the object whose field it
39-
* represents. When the owning object is released, string memory is freed.
40-
*/
41-
typedef struct {
42-
const void *data;
43-
size_t length;
44-
} swiftscan_string_ref_t;
45-
46-
typedef struct {
47-
swiftscan_string_ref_t *strings;
48-
size_t count;
49-
} swiftscan_string_set_t;
26+
//=== Public Dependency Scanner Data Types -------------------------------===//
5027

5128
typedef enum {
5229
// This dependency info encodes two ModuleDependencyKind types:
@@ -368,6 +345,8 @@ swiftscan_scanner_cache_load(swiftscan_scanner_t scanner,
368345
SWIFTSCAN_PUBLIC void
369346
swiftscan_scanner_cache_reset(swiftscan_scanner_t scanner);
370347

348+
//=== Experimental compiler invocation operations -------------------------===//
349+
371350
/// An entry point to invoke the compiler via a library call.
372351
SWIFTSCAN_PUBLIC int invoke_swift_compiler(int argc, const char **argv);
373352

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//===--- LibSwiftScan.h - C API for Swift Dependency Scanning ---*- C ---*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 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+
// This C API is primarily intended to serve as:
14+
// - Swift Driver's dependency scanning facility
15+
// (https://github.com/apple/swift-driver).
16+
// - An object-file scanning facility for extracting of Swift type information
17+
//
18+
//===----------------------------------------------------------------------===//
19+
20+
#ifndef SWIFT_C_SWIFT_SCAN_H
21+
#define SWIFT_C_SWIFT_SCAN_H
22+
23+
/// The version constants for the SwiftDependencyScan C API.
24+
/// SWIFTSCAN_VERSION_MINOR should increase when there are API additions.
25+
/// SWIFTSCAN_VERSION_MAJOR is intended for "major" source/ABI breaking changes.
26+
#define SWIFTSCAN_VERSION_MAJOR 0
27+
#define SWIFTSCAN_VERSION_MINOR 3
28+
29+
#include "DependencyScan.h"
30+
#include "BinaryScan.h"
31+
32+
#endif // SWIFT_C_SWIFT_SCAN_H
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
module _InternalSwiftScan {
2-
header "DependencyScan.h"
2+
header "LibSwiftScan.h"
33
link "_InternalSwiftScan"
44
}

include/swift/Reflection/TypeRefBuilder.h

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -239,9 +239,14 @@ struct FieldTypeInfo {
239239

240240
/// Info about a protocol conformance read out from an Image
241241
struct ProtocolConformanceInfo {
242-
std::string typeName;
243-
std::string protocolName;
244-
std::string mangledTypeName;
242+
std::string TypeName;
243+
std::string ProtocolName;
244+
std::string MangledTypeName;
245+
};
246+
247+
struct ConformanceCollectionResult {
248+
std::vector<ProtocolConformanceInfo> Conformances;
249+
std::vector<std::string> Errors;
245250
};
246251

247252
/// An implementation of MetadataReader's BuilderType concept for
@@ -1171,7 +1176,9 @@ class TypeRefBuilder {
11711176
public:
11721177
template <template <typename Runtime> class ObjCInteropKind,
11731178
unsigned PointerSize>
1174-
void dumpConformanceSection(std::ostream &stream) {
1179+
ConformanceCollectionResult collectAllConformances() {
1180+
ConformanceCollectionResult result;
1181+
11751182
// The Fields section has gathered info on types that includes their mangled
11761183
// names. Use that to build a dictionary from a type's demangled name to its
11771184
// mangeled name
@@ -1203,25 +1210,34 @@ class TypeRefBuilder {
12031210
auto optionalConformanceInfo =
12041211
conformanceReader.readConformanceDescriptor(conformanceAddr,
12051212
typeNameToManglingMap);
1206-
if (!optionalConformanceInfo.hasValue()) {
1207-
stream << "Error reading conformance descriptor: "
1208-
<< conformanceReader.Error << "\n";
1209-
continue;
1210-
}
1211-
auto conformanceInfo = optionalConformanceInfo.getValue();
1212-
auto typeConformancesKey = conformanceInfo.mangledTypeName + " (" +
1213-
conformanceInfo.typeName + ")";
1214-
if (typeConformances.count(typeConformancesKey) != 0) {
1215-
typeConformances[typeConformancesKey].push_back(
1216-
conformanceInfo.protocolName);
1217-
} else {
1218-
typeConformances.emplace(
1219-
typeConformancesKey,
1220-
std::vector<std::string>{conformanceInfo.protocolName});
1221-
}
1213+
if (!optionalConformanceInfo.hasValue())
1214+
result.Errors.push_back(conformanceReader.Error);
1215+
else
1216+
result.Conformances.push_back(optionalConformanceInfo.getValue());
12221217
}
12231218
}
1219+
return result;
1220+
}
12241221

1222+
template <template <typename Runtime> class ObjCInteropKind,
1223+
unsigned PointerSize>
1224+
void dumpConformanceSection(std::ostream &stream) {
1225+
auto conformanceCollectionResult = collectAllConformances<ObjCInteropKind, PointerSize>();
1226+
1227+
// Collect all conformances and aggregate them per-conforming-type.
1228+
std::unordered_map<std::string, std::vector<std::string>> typeConformances;
1229+
for (auto &conformanceInfo : conformanceCollectionResult.Conformances) {
1230+
auto typeConformancesKey = conformanceInfo.MangledTypeName + " (" +
1231+
conformanceInfo.TypeName + ")";
1232+
if (typeConformances.count(typeConformancesKey) != 0) {
1233+
typeConformances[typeConformancesKey].push_back(
1234+
conformanceInfo.ProtocolName);
1235+
} else {
1236+
typeConformances.emplace(
1237+
typeConformancesKey,
1238+
std::vector<std::string>{conformanceInfo.ProtocolName});
1239+
}
1240+
}
12251241
for (auto &pair : typeConformances) {
12261242
stream << pair.first << " : ";
12271243
bool first = true;
@@ -1234,6 +1250,12 @@ class TypeRefBuilder {
12341250
}
12351251
stream << "\n";
12361252
}
1253+
1254+
// Report encountered errors
1255+
for (auto &error : conformanceCollectionResult.Errors) {
1256+
stream << "Error reading conformance descriptor: "
1257+
<< error << "\n";
1258+
}
12371259
}
12381260

12391261
template <template <typename Runtime> class ObjCInteropKind,
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//===---------------- BinaryScanImpl.h - Swift Compiler ------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 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+
// Implementation details of the binary scanning C API
14+
//
15+
//===----------------------------------------------------------------------===//
16+
#ifndef SWIFT_C_BINARY_SCAN_IMPL_H
17+
#define SWIFT_C_BINARY_SCAN_IMPL_H
18+
19+
#include "swift-c/DependencyScan/BinaryScan.h"
20+
21+
namespace swift {
22+
namespace static_mirror {
23+
class BinaryScanningTool;
24+
}
25+
} // namespace swift
26+
27+
struct swiftscan_conformance_info_s {
28+
swiftscan_string_ref_t type_name;
29+
swiftscan_string_ref_t mangled_type_name;
30+
swiftscan_string_ref_t protocol_name;
31+
};
32+
33+
#endif // SWIFT_C_BINARY_SCAN_IMPL_H

0 commit comments

Comments
 (0)