Skip to content

Commit d44ccf8

Browse files
committed
Revert "Rewrite static section bounds discovery in Swift."
This reverts commit e107fa4.
1 parent dbd44fc commit d44ccf8

File tree

5 files changed

+88
-85
lines changed

5 files changed

+88
-85
lines changed

Documentation/Porting.md

+19-20
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,8 @@ emits section information into the resource fork on Classic, you would use the
136136
to load that information:
137137

138138
```diff
139-
--- a/Sources/_TestDiscovery/SectionBounds.swift
140-
+++ b/Sources/_TestDiscovery/SectionBounds.swift
139+
--- a/Sources/Testing/Discovery+Platform.swift
140+
+++ b/Sources/Testing/Discovery+Platform.swift
141141

142142
// ...
143143
+#elseif os(Classic)
@@ -211,30 +211,29 @@ start with `"SWT_"`).
211211
If your platform does not support dynamic linking and loading, you will need to
212212
use static linkage instead. Define the `"SWT_NO_DYNAMIC_LINKING"` compiler
213213
conditional for your platform in both `Package.swift` and
214-
`CompilerSettings.cmake`, then define the symbols `_testContentSectionBegin`,
215-
`_testContentSectionEnd`, `_typeMetadataSectionBegin`, and
216-
`_typeMetadataSectionEnd` in `SectionBounds.swift`:
214+
`CompilerSettings.cmake`, then define the symbols `testContentSectionBegin`,
215+
`testContentSectionEnd`, `typeMetadataSectionBegin`, and
216+
`typeMetadataSectionEnd` in `Discovery.cpp`.
217217

218218
```diff
219-
--- a/Sources/_TestDiscovery/SectionBounds.swift
220-
+++ b/Sources/_TestDiscovery/SectionBounds.swift
219+
diff --git a/Sources/_TestingInternals/Discovery.cpp b/Sources/_TestingInternals/Discovery.cpp
221220
// ...
222-
+#elseif os(Classic)
223-
+@_silgen_name(raw: "...") private nonisolated(unsafe) var _testContentSectionBegin: CChar
224-
+@_silgen_name(raw: "...") private nonisolated(unsafe) var _testContentSectionEnd: CChar
225-
+#if !SWT_NO_LEGACY_TEST_DISCOVERY
226-
+@_silgen_name(raw: "...") private nonisolated(unsafe) var _typeMetadataSectionBegin: CChar
227-
+@_silgen_name(raw: "...") private nonisolated(unsafe) var _typeMetadataSectionEnd: CChar
221+
+#elif defined(macintosh)
222+
+extern "C" const char testContentSectionBegin __asm__("...");
223+
+extern "C" const char testContentSectionEnd __asm__("...");
224+
+#if !defined(SWT_NO_LEGACY_TEST_DISCOVERY)
225+
+extern "C" const char typeMetadataSectionBegin __asm__("...");
226+
+extern "C" const char typeMetadataSectionEnd __asm__("...");
228227
+#endif
229228
#else
230-
#warning("Platform-specific implementation missing: Runtime test discovery unavailable (static)")
231-
private nonisolated(unsafe) var _testContentSectionBegin: Void
232-
private nonisolated(unsafe) var _testContentSectionEnd: Void
233-
#if !SWT_NO_LEGACY_TEST_DISCOVERY
234-
private nonisolated(unsafe) var _typeMetadataSectionBegin: Void
235-
private nonisolated(unsafe) var _typeMetadataSectionEnd: Void
229+
#warning Platform-specific implementation missing: Runtime test discovery unavailable (static)
230+
static const char testContentSectionBegin = 0;
231+
static const char& testContentSectionEnd = testContentSectionBegin;
232+
#if !defined(SWT_NO_LEGACY_TEST_DISCOVERY)
233+
static const char typeMetadataSectionBegin = 0;
234+
static const char& typeMetadataSectionEnd = typeMetadataSectionBegin;
235+
#endif
236236
#endif
237-
// ...
238237
```
239238

240239
These symbols must have unique addresses corresponding to the first byte of the

Sources/_TestDiscovery/SectionBounds.swift

+9-63
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ struct SectionBounds: Sendable {
2323

2424
/// An enumeration describing the different sections discoverable by the
2525
/// testing library.
26-
enum Kind: Equatable, Hashable, CaseIterable {
26+
enum Kind: Int, Equatable, Hashable, CaseIterable {
2727
/// The test content metadata section.
2828
case testContent
2929

@@ -146,7 +146,7 @@ private let _startCollectingSectionBounds: Void = {
146146
///
147147
/// - Returns: An array of structures describing the bounds of all known test
148148
/// content sections in the current process.
149-
private func _sectionBounds(_ kind: SectionBounds.Kind) -> some Sequence<SectionBounds> {
149+
private func _sectionBounds(_ kind: SectionBounds.Kind) -> [SectionBounds] {
150150
_startCollectingSectionBounds
151151
return _sectionBounds.withUnsafeMutablePointers { sectionBounds, lock in
152152
pthread_mutex_lock(lock)
@@ -169,7 +169,7 @@ private import SwiftShims // For MetadataSections
169169
///
170170
/// - Returns: An array of structures describing the bounds of all known test
171171
/// content sections in the current process.
172-
private func _sectionBounds(_ kind: SectionBounds.Kind) -> some Sequence<SectionBounds> {
172+
private func _sectionBounds(_ kind: SectionBounds.Kind) -> [SectionBounds] {
173173
struct Context {
174174
var kind: SectionBounds.Kind
175175
var result = [SectionBounds]()
@@ -297,63 +297,14 @@ private func _sectionBounds(_ kind: SectionBounds.Kind) -> some Sequence<Section
297297
/// - kind: Ignored.
298298
///
299299
/// - Returns: The empty array.
300-
private func _sectionBounds(_ kind: SectionBounds.Kind) -> some Sequence<SectionBounds> {
300+
private func _sectionBounds(_ kind: SectionBounds.Kind) -> [SectionBounds] {
301301
#warning("Platform-specific implementation missing: Runtime test discovery unavailable (dynamic)")
302-
return EmptyCollection()
302+
return []
303303
}
304304
#endif
305305
#else
306306
// MARK: - Statically-linked implementation
307307

308-
/// The bounds of the statically-linked sections of interest to the testing
309-
/// library.
310-
///
311-
/// We use `@_silgen_name(raw:)` to reference these linker-defined symbols.
312-
/// Then, to get their addresses, we must use `&` (`withPointer(to:)` is not
313-
/// guaranteed to avoid a copy in this context.) Hence, they must also be
314-
/// declared `var` rather than `let`, but they should be treated as read-only.
315-
#if SWT_TARGET_OS_APPLE
316-
@_silgen_name(raw: "section$start$__DATA_CONST$__swift5_tests") private nonisolated(unsafe) var _testContentSectionBegin: CChar
317-
@_silgen_name(raw: "section$end$__DATA_CONST$__swift5_tests") private nonisolated(unsafe) var _testContentSectionEnd: CChar
318-
#if !SWT_NO_LEGACY_TEST_DISCOVERY
319-
@_silgen_name(raw: "section$start$__TEXT$__swift5_types") private nonisolated(unsafe) var _typeMetadataSectionBegin: CChar
320-
@_silgen_name(raw: "section$end$__TEXT$__swift5_types") private nonisolated(unsafe) var _typeMetadataSectionEnd: CChar
321-
#endif
322-
#elseif os(WASI)
323-
@_silgen_name(raw: "__start_swift5_tests") private nonisolated(unsafe) var _testContentSectionBegin: CChar
324-
@_silgen_name(raw: "__stop_swift5_tests") private nonisolated(unsafe) var _testContentSectionEnd: CChar
325-
#if !SWT_NO_LEGACY_TEST_DISCOVERY
326-
@_silgen_name(raw: "__start_swift5_type_metadata") private nonisolated(unsafe) var _typeMetadataSectionBegin: CChar
327-
@_silgen_name(raw: "__stop_swift5_type_metadata") private nonisolated(unsafe) var _typeMetadataSectionEnd: CChar
328-
#endif
329-
#else
330-
#warning("Platform-specific implementation missing: Runtime test discovery unavailable (static)")
331-
private nonisolated(unsafe) var _testContentSectionBegin: Void
332-
private nonisolated(unsafe) var _testContentSectionEnd: Void
333-
#if !SWT_NO_LEGACY_TEST_DISCOVERY
334-
private nonisolated(unsafe) var _typeMetadataSectionBegin: Void
335-
private nonisolated(unsafe) var _typeMetadataSectionEnd: Void
336-
#endif
337-
338-
extension UnsafeRawBufferPointer {
339-
/// Construct an empty buffer.
340-
fileprivate init(_: Void = (), sectionBegin _: UnsafeRawPointer, sectionEnd _: UnsafeRawPointer) {
341-
self.init(start: nil, count: 0)
342-
}
343-
}
344-
#endif
345-
346-
extension UnsafeRawBufferPointer {
347-
/// Construct a buffer representing a section's byte bounds.
348-
///
349-
/// - Parameters:
350-
/// - sectionBegin: The address of the first byte of the section.
351-
/// - sectionEnd: The address of the first byte _after_ the section.
352-
@_disfavoredOverload fileprivate init(sectionBegin: UnsafeRawPointer, sectionEnd: UnsafeRawPointer) {
353-
self.init(start: sectionBegin, count: sectionEnd - sectionBegin)
354-
}
355-
}
356-
357308
/// The common implementation of ``SectionBounds/all(_:)`` for platforms that do
358309
/// not support dynamic linking.
359310
///
@@ -362,15 +313,10 @@ extension UnsafeRawBufferPointer {
362313
///
363314
/// - Returns: A structure describing the bounds of the type metadata section
364315
/// contained in the same image as the testing library itself.
365-
private func _sectionBounds(_ kind: SectionBounds.Kind) -> some Sequence<SectionBounds> {
366-
let buffer = switch kind {
367-
case .testContent:
368-
UnsafeRawBufferPointer(sectionBegin: &_testContentSectionBegin, sectionEnd: &_testContentSectionEnd)
369-
#if !SWT_NO_LEGACY_TEST_DISCOVERY
370-
case .typeMetadata:
371-
UnsafeRawBufferPointer(sectionBegin: &_typeMetadataSectionBegin, sectionEnd: &_typeMetadataSectionEnd)
372-
#endif
373-
}
316+
private func _sectionBounds(_ kind: SectionBounds.Kind) -> CollectionOfOne<SectionBounds> {
317+
var (baseAddress, count): (UnsafeRawPointer?, Int) = (nil, 0)
318+
swt_getStaticallyLinkedSectionBounds(kind.rawValue, &baseAddress, &count)
319+
let buffer = UnsafeRawBufferPointer(start: baseAddress, count: count)
374320
let sb = SectionBounds(imageAddress: nil, buffer: buffer)
375321
return CollectionOfOne(sb)
376322
}

Sources/_TestDiscovery/TestContentRecord.swift

+1-2
Original file line numberDiff line numberDiff line change
@@ -276,8 +276,7 @@ extension DiscoverableAsTestContent where Self: ~Copyable {
276276
}
277277

278278
let result = SectionBounds.all(.typeMetadata).lazy.flatMap { sb in
279-
stride(from: 0, to: sb.buffer.count, by: SWTTypeMetadataRecordByteCount).lazy
280-
.map { sb.buffer.baseAddress! + $0 }
279+
stride(from: sb.buffer.baseAddress!, to: sb.buffer.baseAddress! + sb.buffer.count, by: SWTTypeMetadataRecordByteCount).lazy
281280
.compactMap { swt_getType(fromTypeMetadataRecord: $0, ifNameContains: typeNameHint) }
282281
.map { unsafeBitCast($0, to: Any.Type.self) }
283282
.compactMap(loader)

Sources/_TestingInternals/Discovery.cpp

+44
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,55 @@
1010

1111
#include "Discovery.h"
1212

13+
#include <algorithm>
1314
#if !defined(SWT_NO_LEGACY_TEST_DISCOVERY)
1415
#include <cstdint>
1516
#include <cstring>
1617
#include <type_traits>
18+
#endif
19+
20+
#if defined(SWT_NO_DYNAMIC_LINKING)
21+
#pragma mark - Statically-linked section bounds
1722

23+
#if defined(__APPLE__)
24+
extern "C" const char testContentSectionBegin __asm("section$start$__DATA_CONST$__swift5_tests");
25+
extern "C" const char testContentSectionEnd __asm("section$end$__DATA_CONST$__swift5_tests");
26+
#if !defined(SWT_NO_LEGACY_TEST_DISCOVERY)
27+
extern "C" const char typeMetadataSectionBegin __asm__("section$start$__TEXT$__swift5_types");
28+
extern "C" const char typeMetadataSectionEnd __asm__("section$end$__TEXT$__swift5_types");
29+
#endif
30+
#elif defined(__wasi__)
31+
extern "C" const char testContentSectionBegin __asm__("__start_swift5_tests");
32+
extern "C" const char testContentSectionEnd __asm__("__stop_swift5_tests");
33+
#if !defined(SWT_NO_LEGACY_TEST_DISCOVERY)
34+
extern "C" const char typeMetadataSectionBegin __asm__("__start_swift5_type_metadata");
35+
extern "C" const char typeMetadataSectionEnd __asm__("__stop_swift5_type_metadata");
36+
#endif
37+
#else
38+
#warning Platform-specific implementation missing: Runtime test discovery unavailable (static)
39+
static const char testContentSectionBegin = 0;
40+
static const char& testContentSectionEnd = testContentSectionBegin;
41+
#if !defined(SWT_NO_LEGACY_TEST_DISCOVERY)
42+
static const char typeMetadataSectionBegin = 0;
43+
static const char& typeMetadataSectionEnd = typeMetadataSectionBegin;
44+
#endif
45+
#endif
46+
47+
static constexpr const char *const staticallyLinkedSectionBounds[][2] = {
48+
{ &testContentSectionBegin, &testContentSectionEnd },
49+
#if !defined(SWT_NO_LEGACY_TEST_DISCOVERY)
50+
{ &typeMetadataSectionBegin, &typeMetadataSectionEnd },
51+
#endif
52+
};
53+
54+
void swt_getStaticallyLinkedSectionBounds(size_t kind, const void **outSectionBegin, size_t *outByteCount) {
55+
auto [sectionBegin, sectionEnd] = staticallyLinkedSectionBounds[kind];
56+
*outSectionBegin = sectionBegin;
57+
*outByteCount = std::distance(sectionBegin, sectionEnd);
58+
}
59+
#endif
60+
61+
#if !defined(SWT_NO_LEGACY_TEST_DISCOVERY)
1862
#pragma mark - Swift ABI
1963

2064
#if defined(__PTRAUTH_INTRINSICS__)

Sources/_TestingInternals/include/Discovery.h

+15
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,21 @@ SWT_IMPORT_FROM_STDLIB void swift_enumerateAllMetadataSections(
3030
);
3131
#endif
3232

33+
#pragma mark - Statically-linked section bounds
34+
35+
/// Get the bounds of a statically linked section in this image.
36+
///
37+
/// - Parameters:
38+
/// - kind: The value of `SectionBounds.Kind.rawValue` for the given section.
39+
/// - outSectionBegin: On return, a pointer to the first byte of the section.
40+
/// - outByteCount: On return, the number of bytes in the section.
41+
///
42+
/// - Note: This symbol is _declared_, but not _defined_, on platforms with
43+
/// dynamic linking because the `SWT_NO_DYNAMIC_LINKING` C++ macro (not the
44+
/// Swift compiler conditional of the same name) is not consistently declared
45+
/// when Swift files import the `_TestingInternals` C++ module.
46+
SWT_EXTERN void swt_getStaticallyLinkedSectionBounds(size_t kind, const void *_Nullable *_Nonnull outSectionBegin, size_t *outByteCount);
47+
3348
#pragma mark - Legacy test discovery
3449

3550
/// The size, in bytes, of a Swift type metadata record.

0 commit comments

Comments
 (0)