Skip to content

Commit 55f9d2a

Browse files
authored
Merge pull request #27863 from mikeash/will-throw-callback
[Runtime] Add a function pointer for intercepting swift_willThrow calls.
2 parents dfd805f + 09e2e68 commit 55f9d2a

File tree

9 files changed

+140
-46
lines changed

9 files changed

+140
-46
lines changed

stdlib/private/StdlibUnittest/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ add_swift_target_library(swiftStdlibUnittest ${SWIFT_STDLIB_LIBRARY_BUILD_TYPES}
2727
Statistics.swift
2828
StdlibCoreExtras.swift
2929
StringConvertible.swift
30+
SymbolLookup.swift
3031
TestHelpers.swift
3132
TypeIndexed.swift
3233

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//===--- SymbolLookup.swift -----------------------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2019 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+
#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)
14+
import Darwin
15+
#elseif os(Linux) || os(FreeBSD) || os(PS4) || os(Android) || os(Cygwin) || os(Haiku)
16+
import Glibc
17+
#elseif os(Windows)
18+
import MSVCRT
19+
import WinSDK
20+
#else
21+
#error("Unsupported platform")
22+
#endif
23+
24+
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
25+
let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: -2)
26+
#elseif os(Linux)
27+
let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: 0)
28+
#elseif os(Android)
29+
#if arch(arm)
30+
let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: 0xffffffff as UInt)
31+
#elseif arch(arm64)
32+
let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: 0)
33+
#else
34+
#error("Unsupported platform")
35+
#endif
36+
#elseif os(Windows)
37+
let hStdlibCore: HMODULE = GetModuleHandleA("swiftCore.dll")!
38+
#else
39+
#error("Unsupported platform")
40+
#endif
41+
42+
public func pointerToSwiftCoreSymbol(name: String) -> UnsafeMutableRawPointer? {
43+
#if os(Windows)
44+
return unsafeBitCast(GetProcAddress(hStdlibCore, name),
45+
to: UnsafeMutableRawPointer?.self)
46+
#else
47+
return dlsym(RTLD_DEFAULT, name)
48+
#endif
49+
}

stdlib/public/runtime/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ set(swift_runtime_sources
3737
CygwinPort.cpp
3838
Demangle.cpp
3939
Enum.cpp
40+
ErrorObjectCommon.cpp
4041
ErrorObjectConstants.cpp
4142
ErrorObjectNative.cpp
4243
Errors.cpp

stdlib/public/runtime/ErrorObject.mm

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -598,12 +598,5 @@ ProtocolDescriptorRef theErrorProtocol(&PROTOCOL_DESCR_SYM(s5Error),
598598
return objc_release((id)error);
599599
}
600600

601-
/// Breakpoint hook for debuggers.
602-
SWIFT_CC(swift) void
603-
swift::swift_willThrow(SWIFT_CONTEXT void *unused,
604-
SWIFT_ERROR_RESULT SwiftError **error) {
605-
// empty
606-
}
607-
608601
#endif
609602

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//===--- ErrorObjectCommon.cpp - Recoverable error object -----------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2019 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 implements the parts of the standard Error protocol type which are
14+
// shared between the ObjC-interoperable implementation and the native
15+
// implementation. The parts specific to each implementation can be found in
16+
// ErrorObject.mm (for the ObjC-interoperable parts) and ErrorObjectNative.cpp.
17+
//
18+
//===----------------------------------------------------------------------===//
19+
20+
#include "swift/Runtime/Concurrent.h"
21+
#include "swift/Runtime/Config.h"
22+
#include "ErrorObject.h"
23+
#include "ErrorObjectTestSupport.h"
24+
25+
using namespace swift;
26+
27+
void (*swift::_swift_willThrow)(SwiftError *error);
28+
29+
/// Breakpoint hook for debuggers, and calls _swift_willThrow if set.
30+
SWIFT_CC(swift) void
31+
swift::swift_willThrow(SWIFT_CONTEXT void *unused,
32+
SWIFT_ERROR_RESULT SwiftError **error) {
33+
// Cheap check to bail out early, since we expect there to be no callbacks
34+
// the vast majority of the time.
35+
if (SWIFT_LIKELY(!_swift_willThrow))
36+
return;
37+
_swift_willThrow(*error);
38+
}

stdlib/public/runtime/ErrorObjectNative.cpp

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -106,11 +106,4 @@ swift::swift_getErrorValue(const SwiftError *errorObject,
106106
out->errorConformance = errorObject->errorConformance;
107107
}
108108

109-
/// Breakpoint hook for debuggers.
110-
SWIFT_CC(swift) void
111-
swift::swift_willThrow(SWIFT_CONTEXT void *unused,
112-
SWIFT_ERROR_RESULT SwiftError **error) {
113-
// do nothing
114-
}
115-
116109
#endif
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//===--- ErrorObjectTestSupport.h - Support for Instruments.app -*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2019 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+
// Swift runtime support for tests involving errors.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef SWIFT_RUNTIME_ERROROBJECT_TEST_SUPPORT_H
18+
#define SWIFT_RUNTIME_ERROROBJECT_TEST_SUPPORT_H
19+
20+
namespace swift {
21+
22+
SWIFT_RUNTIME_EXPORT void (*_swift_willThrow)(SwiftError *error);
23+
24+
}
25+
26+
#endif

test/stdlib/Error.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,5 +191,28 @@ ErrorTests.test("test dealloc empty error box") {
191191
}
192192
}
193193

194+
var errors: [Error] = []
195+
ErrorTests.test("willThrow") {
196+
// Error isn't allowed in a @convention(c) function when ObjC interop is
197+
// not available, so pass it through an OpaquePointer.
198+
typealias WillThrow = @convention(c) (OpaquePointer) -> Void
199+
let willThrow = pointerToSwiftCoreSymbol(name: "_swift_willThrow")!
200+
let callback: WillThrow = {
201+
errors.append(unsafeBitCast($0, to: Error.self))
202+
}
203+
willThrow.storeBytes(of: callback, as: WillThrow.self)
204+
expectTrue(errors.isEmpty)
205+
do {
206+
throw UnsignedError.negativeOne
207+
} catch {}
208+
expectEqual(UnsignedError.self, type(of: errors.last!))
209+
210+
do {
211+
throw SillyError.JazzHands
212+
} catch {}
213+
expectEqual(2, errors.count)
214+
expectEqual(SillyError.self, type(of: errors.last!))
215+
}
216+
194217
runAllTests()
195218

test/stdlib/Runtime.swift.gyb

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -592,39 +592,9 @@ Runtime.test("Struct layout with reference storage types") {
592592
}
593593

594594
Runtime.test("SwiftError layout constants for LLDB") {
595-
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
596-
let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: -2)
597-
#elseif os(Linux)
598-
let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: 0)
599-
#elseif os(Android)
600-
#if arch(arm)
601-
let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: 0xffffffff as UInt)
602-
#elseif arch(arm64)
603-
let RTLD_DEFAULT = UnsafeMutableRawPointer(bitPattern: 0)
604-
#else
605-
_UnimplementedError()
606-
#endif
607-
#elseif os(Windows)
608-
let hStdlibCore: HMODULE = GetModuleHandleA("swiftCore.dll")!
609-
#else
610-
_UnimplementedError()
611-
#endif
595+
let offsetof_SwiftError_typeMetadata = pointerToSwiftCoreSymbol(name: "_swift_lldb_offsetof_SwiftError_typeMetadata")!
596+
let sizeof_SwiftError = pointerToSwiftCoreSymbol(name: "_swift_lldb_sizeof_SwiftError")!
612597

613-
#if os(Windows)
614-
let offsetof_SwiftError_typeMetadata: UnsafeRawPointer =
615-
unsafeBitCast(GetProcAddress(hStdlibCore,
616-
"_swift_lldb_offsetof_SwiftError_typeMetadata")!,
617-
to: UnsafeRawPointer.self)
618-
let sizeof_SwiftError: UnsafeRawPointer =
619-
unsafeBitCast(GetProcAddress(hStdlibCore,
620-
"_swift_lldb_sizeof_SwiftError")!,
621-
to: UnsafeRawPointer.self)
622-
#else
623-
let offsetof_SwiftError_typeMetadata =
624-
dlsym(RTLD_DEFAULT, "_swift_lldb_offsetof_SwiftError_typeMetadata")!
625-
let sizeof_SwiftError =
626-
dlsym(RTLD_DEFAULT, "_swift_lldb_sizeof_SwiftError")!
627-
#endif
628598
#if os(macOS) || os(iOS) || os(watchOS) || os(tvOS)
629599
#if arch(i386) || arch(arm)
630600
expectEqual(20, offsetof_SwiftError_typeMetadata.load(as: UInt.self))

0 commit comments

Comments
 (0)