mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
For two reasons: * We also like to check for assert failures in release builds. Although this could be achieved with `precondition`, it's easy to forget about it and use `assert` instead. * We need to see the error message in crashlogs of release builds. This is even not the case for `precondition`. Also, re-export the "Basic" module in "SIL" so that the new assert implementation is also available in the Optimizer module (where all files import SIL).
135 lines
4.8 KiB
Swift
135 lines
4.8 KiB
Swift
//===--- Utils.swift - Some bridging utilities ----------------------------===//
|
|
//
|
|
// This source file is part of the Swift.org open source project
|
|
//
|
|
// Copyright (c) 2022 Apple Inc. and the Swift project authors
|
|
// Licensed under Apache License v2.0 with Runtime Library Exception
|
|
//
|
|
// See https://swift.org/LICENSE.txt for license information
|
|
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
@_exported import BasicBridging
|
|
import std
|
|
|
|
/// The assert function to be used in the compiler.
|
|
///
|
|
/// This overrides the standard Swift assert for two reasons:
|
|
/// * We also like to check for assert failures in release builds. Although this could be
|
|
/// achieved with `precondition`, it's easy to forget about it and use `assert` instead.
|
|
/// * We need to see the error message in crashlogs of release builds. This is even not the
|
|
/// case for `precondition`.
|
|
@_transparent
|
|
public func assert(_ condition: Bool, _ message: @autoclosure () -> String,
|
|
file: StaticString = #fileID, line: UInt = #line) {
|
|
if !condition {
|
|
print("### basic")
|
|
fatalError(message(), file: file, line: line)
|
|
}
|
|
}
|
|
|
|
/// The assert function (without a message) to be used in the compiler.
|
|
///
|
|
/// Unforuntately it's not possible to just add a default argument to `message` in the
|
|
/// other `assert` function. We need to defined this overload.
|
|
@_transparent
|
|
public func assert(_ condition: Bool, file: StaticString = #fileID, line: UInt = #line) {
|
|
if !condition {
|
|
fatalError("", file: file, line: line)
|
|
}
|
|
}
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// StringRef
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
public struct StringRef : CustomStringConvertible, CustomReflectable {
|
|
let _bridged: llvm.StringRef
|
|
|
|
public init(bridged: llvm.StringRef) { self._bridged = bridged }
|
|
|
|
public var string: String { _bridged.string }
|
|
public var description: String { string }
|
|
public var customMirror: Mirror { Mirror(self, children: []) }
|
|
|
|
public static func ==(lhs: StringRef, rhs: StaticString) -> Bool {
|
|
let lhsBuffer = UnsafeBufferPointer<UInt8>(
|
|
start: lhs._bridged.__bytes_beginUnsafe(),
|
|
count: Int(lhs._bridged.__bytes_endUnsafe() - lhs._bridged.__bytes_beginUnsafe()))
|
|
return rhs.withUTF8Buffer { (rhsBuffer: UnsafeBufferPointer<UInt8>) in
|
|
if lhsBuffer.count != rhsBuffer.count { return false }
|
|
return lhsBuffer.elementsEqual(rhsBuffer, by: ==)
|
|
}
|
|
}
|
|
|
|
public static func !=(lhs: StringRef, rhs: StaticString) -> Bool { !(lhs == rhs) }
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Bridging Utilities
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
extension llvm.StringRef {
|
|
public var string: String {
|
|
String(_cxxString: self.str())
|
|
}
|
|
}
|
|
|
|
extension String {
|
|
/// Underscored to avoid name collision with Swift LLVM Bindings.
|
|
/// To be replaced with a bindings call once bindings are a dependency.
|
|
public func _withStringRef<T>(_ c: (llvm.StringRef) -> T) -> T {
|
|
var str = self
|
|
return str.withUTF8 { buffer in
|
|
return c(llvm.StringRef(buffer.baseAddress, buffer.count))
|
|
}
|
|
}
|
|
|
|
/// Underscored to avoid name collision with the std overlay.
|
|
/// To be replaced with an overlay call once the CI uses SDKs built with Swift 5.8.
|
|
public init(_cxxString s: std.string) {
|
|
self.init(cString: s.__c_strUnsafe())
|
|
withExtendedLifetime(s) {}
|
|
}
|
|
}
|
|
|
|
extension Array {
|
|
public func withBridgedArrayRef<T>(_ c: (BridgedArrayRef) -> T) -> T {
|
|
return withUnsafeBytes { buf in
|
|
return c(BridgedArrayRef(data: buf.baseAddress!, numElements: count))
|
|
}
|
|
}
|
|
}
|
|
|
|
public typealias SwiftObject = UnsafeMutablePointer<BridgedSwiftObject>
|
|
|
|
extension UnsafeMutablePointer where Pointee == BridgedSwiftObject {
|
|
public init<T: AnyObject>(_ object: T) {
|
|
let ptr = Unmanaged.passUnretained(object).toOpaque()
|
|
self = ptr.bindMemory(to: BridgedSwiftObject.self, capacity: 1)
|
|
}
|
|
|
|
public func getAs<T: AnyObject>(_ objectType: T.Type) -> T {
|
|
return Unmanaged<T>.fromOpaque(self).takeUnretainedValue()
|
|
}
|
|
}
|
|
|
|
extension Optional where Wrapped == UnsafeMutablePointer<BridgedSwiftObject> {
|
|
public func getAs<T: AnyObject>(_ objectType: T.Type) -> T? {
|
|
if let pointer = self {
|
|
return Unmanaged<T>.fromOpaque(pointer).takeUnretainedValue()
|
|
}
|
|
return nil
|
|
}
|
|
}
|
|
|
|
extension BridgedArrayRef {
|
|
public func withElements<T, R>(ofType ty: T.Type, _ c: (UnsafeBufferPointer<T>) -> R) -> R {
|
|
let start = data?.bindMemory(to: ty, capacity: numElements);
|
|
let buffer = UnsafeBufferPointer(start: start, count: numElements);
|
|
return c(buffer)
|
|
}
|
|
}
|