| //===----------------------------------------------------------*- swift -*-===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See http://swift.org/LICENSE.txt for license information |
| // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------===// |
| /// |
| /// This file contains Swift wrappers for functions defined in the C++ runtime. |
| /// |
| //===----------------------------------------------------------------------===// |
| |
| import SwiftShims |
| |
| //===----------------------------------------------------------------------===// |
| // Atomics |
| //===----------------------------------------------------------------------===// |
| |
| @_transparent |
| @warn_unused_result |
| public // @testable |
| func _stdlib_atomicCompareExchangeStrongPtrImpl( |
| object target: UnsafeMutablePointer<COpaquePointer>, |
| expected: UnsafeMutablePointer<COpaquePointer>, |
| desired: COpaquePointer) -> Bool { |
| |
| let (oldValue, won) = Builtin.cmpxchg_seqcst_seqcst_RawPointer( |
| target._rawValue, expected.memory._rawValue, desired._rawValue) |
| expected.memory._rawValue = oldValue |
| return Bool(won) |
| } |
| |
| /// Atomic compare and exchange of `UnsafeMutablePointer<T>` with sequentially |
| /// consistent memory ordering. Precise semantics are defined in C++11 or C11. |
| /// |
| /// - Warning: This operation is extremely tricky to use correctly because of |
| /// writeback semantics. |
| /// |
| /// It is best to use it directly on an |
| /// `UnsafeMutablePointer<UnsafeMutablePointer<T>>` that is known to point |
| /// directly to the memory where the value is stored. |
| /// |
| /// In a call like this: |
| /// |
| /// _stdlib_atomicCompareExchangeStrongPtr(&foo.property1.property2, ...) |
| /// |
| /// you need to manually make sure that: |
| /// |
| /// - all properties in the chain are physical (to make sure that no writeback |
| /// happens; the compare-and-exchange instruction should operate on the |
| /// shared memory); and |
| /// |
| /// - the shared memory that you are accessing is located inside a heap |
| /// allocation (a class instance property, a `_HeapBuffer`, a pointer to |
| /// an `Array` element etc.) |
| /// |
| /// If the conditions above are not met, the code will still compile, but the |
| /// compare-and-exchange instruction will operate on the writeback buffer, and |
| /// you will get a *race* while doing writeback into shared memory. |
| @_transparent |
| @warn_unused_result |
| public // @testable |
| func _stdlib_atomicCompareExchangeStrongPtr<T>( |
| object target: UnsafeMutablePointer<UnsafeMutablePointer<T>>, |
| expected: UnsafeMutablePointer<UnsafeMutablePointer<T>>, |
| desired: UnsafeMutablePointer<T>) -> Bool { |
| return _stdlib_atomicCompareExchangeStrongPtrImpl( |
| object: UnsafeMutablePointer(target), |
| expected: UnsafeMutablePointer(expected), |
| desired: COpaquePointer(desired)) |
| } |
| |
| @_transparent |
| public // @testable |
| func _stdlib_atomicInitializeARCRef( |
| object target: UnsafeMutablePointer<AnyObject?>, |
| desired: AnyObject) -> Bool { |
| var expected = COpaquePointer() |
| let desiredPtr = Unmanaged.passRetained(desired).toOpaque() |
| let wonRace = _stdlib_atomicCompareExchangeStrongPtrImpl( |
| object: UnsafeMutablePointer(target), |
| expected: &expected, |
| desired: desiredPtr) |
| if !wonRace { |
| // Some other thread initialized the value. Balance the retain that we |
| // performed on 'desired'. |
| Unmanaged.passUnretained(desired).release() |
| } |
| return wonRace |
| } |
| |
| % for bits in [ 32, 64 ]: |
| |
| @warn_unused_result |
| @_transparent |
| public // @testable |
| func _stdlib_atomicCompareExchangeStrongUInt${bits}( |
| object target: UnsafeMutablePointer<UInt${bits}>, |
| expected: UnsafeMutablePointer<UInt${bits}>, |
| desired: UInt${bits}) -> Bool { |
| |
| let (oldValue, won) = Builtin.cmpxchg_seqcst_seqcst_Int${bits}( |
| target._rawValue, expected.memory._value, desired._value) |
| expected.memory._value = oldValue |
| return Bool(won) |
| } |
| |
| @warn_unused_result |
| @_transparent |
| public // @testable |
| func _stdlib_atomicCompareExchangeStrongInt${bits}( |
| object target: UnsafeMutablePointer<Int${bits}>, |
| expected: UnsafeMutablePointer<Int${bits}>, |
| desired: Int${bits}) -> Bool { |
| return _stdlib_atomicCompareExchangeStrongUInt${bits}( |
| object: UnsafeMutablePointer(target), |
| expected: UnsafeMutablePointer(expected), |
| desired: UInt${bits}(bitPattern: desired)) |
| } |
| |
| @_transparent |
| public // @testable |
| func _swift_stdlib_atomicStoreUInt${bits}( |
| object target: UnsafeMutablePointer<UInt${bits}>, |
| desired: UInt${bits}) { |
| |
| Builtin.atomicstore_seqcst_Int${bits}(target._rawValue, desired._value) |
| } |
| |
| func _swift_stdlib_atomicStoreInt${bits}( |
| object target: UnsafeMutablePointer<Int${bits}>, |
| desired: Int${bits}) { |
| return _swift_stdlib_atomicStoreUInt${bits}( |
| object: UnsafeMutablePointer(target), |
| desired: UInt${bits}(bitPattern: desired)) |
| } |
| |
| @warn_unused_result |
| public // @testable |
| func _swift_stdlib_atomicLoadUInt${bits}( |
| object target: UnsafeMutablePointer<UInt${bits}>) -> UInt${bits} { |
| |
| let value = Builtin.atomicload_seqcst_Int${bits}(target._rawValue) |
| return UInt${bits}(value) |
| } |
| |
| @warn_unused_result |
| func _swift_stdlib_atomicLoadInt${bits}( |
| object target: UnsafeMutablePointer<Int${bits}>) -> Int${bits} { |
| return Int${bits}(bitPattern: |
| _swift_stdlib_atomicLoadUInt${bits}( |
| object: UnsafeMutablePointer(target))) |
| } |
| |
| % for operation in [ 'Add', 'And', 'Or', 'Xor' ]: |
| // Warning: no overflow checking. |
| @_transparent |
| public // @testable |
| func _swift_stdlib_atomicFetch${operation}UInt${bits}( |
| object target: UnsafeMutablePointer<UInt${bits}>, |
| operand: UInt${bits}) -> UInt${bits} { |
| |
| let value = Builtin.atomicrmw_${operation.lower()}_seqcst_Int${bits}( |
| target._rawValue, operand._value) |
| |
| return UInt${bits}(value) |
| } |
| |
| // Warning: no overflow checking. |
| @warn_unused_result |
| func _swift_stdlib_atomicFetch${operation}Int${bits}( |
| object target: UnsafeMutablePointer<Int${bits}>, |
| operand: Int${bits}) -> Int${bits} { |
| return Int${bits}(bitPattern: |
| _swift_stdlib_atomicFetch${operation}UInt${bits}( |
| object: UnsafeMutablePointer(target), |
| operand: UInt${bits}(bitPattern: operand))) |
| } |
| % end |
| |
| % end |
| |
| @warn_unused_result |
| func _stdlib_atomicCompareExchangeStrongInt( |
| object target: UnsafeMutablePointer<Int>, |
| expected: UnsafeMutablePointer<Int>, |
| desired: Int) -> Bool { |
| #if arch(i386) || arch(arm) |
| return _stdlib_atomicCompareExchangeStrongUInt32( |
| object: UnsafeMutablePointer(target), |
| expected: UnsafeMutablePointer(expected), |
| desired: UInt32(bitPattern: Int32(desired))) |
| #elseif arch(x86_64) || arch(arm64) |
| return _stdlib_atomicCompareExchangeStrongUInt64( |
| object: UnsafeMutablePointer(target), |
| expected: UnsafeMutablePointer(expected), |
| desired: UInt64(bitPattern: Int64(desired))) |
| #endif |
| } |
| |
| func _swift_stdlib_atomicStoreInt( |
| object target: UnsafeMutablePointer<Int>, |
| desired: Int) { |
| #if arch(i386) || arch(arm) |
| return _swift_stdlib_atomicStoreUInt32( |
| object: UnsafeMutablePointer(target), |
| desired: UInt32(bitPattern: Int32(desired))) |
| #elseif arch(x86_64) || arch(arm64) |
| return _swift_stdlib_atomicStoreUInt64( |
| object: UnsafeMutablePointer(target), |
| desired: UInt64(bitPattern: Int64(desired))) |
| #endif |
| } |
| |
| @_transparent |
| @warn_unused_result |
| public func _swift_stdlib_atomicLoadInt( |
| object target: UnsafeMutablePointer<Int>) -> Int { |
| #if arch(i386) || arch(arm) |
| return Int(Int32(bitPattern: |
| _swift_stdlib_atomicLoadUInt32( |
| object: UnsafeMutablePointer(target)))) |
| #elseif arch(x86_64) || arch(arm64) |
| return Int(Int64(bitPattern: |
| _swift_stdlib_atomicLoadUInt64( |
| object: UnsafeMutablePointer(target)))) |
| #endif |
| } |
| |
| @warn_unused_result |
| @_transparent |
| public // @testable |
| func _swift_stdlib_atomicLoadPtrImpl( |
| object target: UnsafeMutablePointer<COpaquePointer> |
| ) -> COpaquePointer { |
| let value = Builtin.atomicload_seqcst_RawPointer(target._rawValue) |
| return COpaquePointer(value) |
| } |
| |
| @_transparent |
| @warn_unused_result |
| public // @testable |
| func _stdlib_atomicLoadARCRef( |
| object target: UnsafeMutablePointer<AnyObject?> |
| ) -> AnyObject? { |
| let result = _swift_stdlib_atomicLoadPtrImpl( |
| object: UnsafeMutablePointer(target)) |
| if result != nil { |
| return Unmanaged<AnyObject>.fromOpaque(result).takeUnretainedValue() |
| } |
| return nil |
| } |
| |
| % for operation in [ 'Add', 'And', 'Or', 'Xor' ]: |
| // Warning: no overflow checking. |
| public func _swift_stdlib_atomicFetch${operation}Int( |
| object target: UnsafeMutablePointer<Int>, |
| operand: Int) -> Int { |
| #if arch(i386) || arch(arm) |
| return Int(Int32(bitPattern: |
| _swift_stdlib_atomicFetch${operation}UInt32( |
| object: UnsafeMutablePointer(target), |
| operand: UInt32(bitPattern: Int32(operand))))) |
| #elseif arch(x86_64) || arch(arm64) |
| return Int(Int64(bitPattern: |
| _swift_stdlib_atomicFetch${operation}UInt64( |
| object: UnsafeMutablePointer(target), |
| operand: UInt64(bitPattern: Int64(operand))))) |
| #endif |
| } |
| % end |
| |
| public final class _stdlib_AtomicInt { |
| var _value: Int |
| |
| var _valuePtr: UnsafeMutablePointer<Int> { |
| return UnsafeMutablePointer(_getUnsafePointerToStoredProperties(self)) |
| } |
| |
| public init(_ value: Int = 0) { |
| _value = value |
| } |
| |
| public func store(desired: Int) { |
| return _swift_stdlib_atomicStoreInt(object: _valuePtr, desired: desired) |
| } |
| |
| @warn_unused_result |
| public func load() -> Int { |
| return _swift_stdlib_atomicLoadInt(object: _valuePtr) |
| } |
| |
| % for operation_name, operation in [ ('Add', '+'), ('And', '&'), ('Or', '|'), ('Xor', '^') ]: |
| public func fetchAnd${operation_name}(operand: Int) -> Int { |
| return _swift_stdlib_atomicFetch${operation_name}Int( |
| object: _valuePtr, |
| operand: operand) |
| } |
| |
| public func ${operation_name.lower()}AndFetch(operand: Int) -> Int { |
| return fetchAnd${operation_name}(operand) ${operation} operand |
| } |
| % end |
| |
| @warn_unused_result |
| public func compareExchange( |
| inout expected expected: Int, desired: Int |
| ) -> Bool { |
| var expectedVar = expected |
| let result = _stdlib_atomicCompareExchangeStrongInt( |
| object: _valuePtr, |
| expected: &expectedVar, |
| desired: desired) |
| expected = expectedVar |
| return result |
| } |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // Conversion of primitive types to `String` |
| //===----------------------------------------------------------------------===// |
| |
| /// A 32 byte buffer. |
| struct _Buffer32 { |
| var x0: UInt64 = 0 |
| var x1: UInt64 = 0 |
| var x2: UInt64 = 0 |
| var x3: UInt64 = 0 |
| } |
| |
| /// A 72 byte buffer. |
| struct _Buffer72 { |
| var x0: UInt64 = 0 |
| var x1: UInt64 = 0 |
| var x2: UInt64 = 0 |
| var x3: UInt64 = 0 |
| var x4: UInt64 = 0 |
| var x5: UInt64 = 0 |
| var x6: UInt64 = 0 |
| var x7: UInt64 = 0 |
| var x8: UInt64 = 0 |
| } |
| |
| % for bits in [ 32, 64, 80 ]: |
| |
| % if bits == 80: |
| #if arch(i386) || arch(x86_64) |
| % end |
| |
| @warn_unused_result |
| @_silgen_name("swift_float${bits}ToString") |
| func _float${bits}ToStringImpl( |
| buffer: UnsafeMutablePointer<UTF8.CodeUnit>, |
| _ bufferLength: UInt, _ value: Float${bits}, |
| _ debug: Bool |
| ) -> UInt |
| |
| @warn_unused_result |
| func _float${bits}ToString(value: Float${bits}, debug: Bool) -> String { |
| _sanityCheck(sizeof(_Buffer32.self) == 32) |
| _sanityCheck(sizeof(_Buffer72.self) == 72) |
| |
| var buffer = _Buffer32() |
| return withUnsafeMutablePointer(&buffer) { |
| (bufferPtr) in |
| let bufferUTF8Ptr = UnsafeMutablePointer<UTF8.CodeUnit>(bufferPtr) |
| let actualLength = _float${bits}ToStringImpl(bufferUTF8Ptr, 32, value, debug) |
| return String._fromWellFormedCodeUnitSequence( |
| UTF8.self, |
| input: UnsafeBufferPointer( |
| start: bufferUTF8Ptr, count: Int(actualLength))) |
| } |
| } |
| |
| % if bits == 80: |
| #endif |
| % end |
| |
| % end |
| |
| @warn_unused_result |
| @_silgen_name("swift_int64ToString") |
| func _int64ToStringImpl( |
| buffer: UnsafeMutablePointer<UTF8.CodeUnit>, |
| _ bufferLength: UInt, _ value: Int64, |
| _ radix: Int64, _ uppercase: Bool |
| ) -> UInt |
| |
| @warn_unused_result |
| func _int64ToString( |
| value: Int64, radix: Int64 = 10, uppercase: Bool = false |
| ) -> String { |
| if radix >= 10 { |
| var buffer = _Buffer32() |
| return withUnsafeMutablePointer(&buffer) { |
| (bufferPtr) in |
| let bufferUTF8Ptr = UnsafeMutablePointer<UTF8.CodeUnit>(bufferPtr) |
| let actualLength = |
| _int64ToStringImpl(bufferUTF8Ptr, 32, value, radix, uppercase) |
| return String._fromWellFormedCodeUnitSequence( |
| UTF8.self, |
| input: UnsafeBufferPointer( |
| start: bufferUTF8Ptr, count: Int(actualLength))) |
| } |
| } else { |
| var buffer = _Buffer72() |
| return withUnsafeMutablePointer(&buffer) { |
| (bufferPtr) in |
| let bufferUTF8Ptr = UnsafeMutablePointer<UTF8.CodeUnit>(bufferPtr) |
| let actualLength = |
| _int64ToStringImpl(bufferUTF8Ptr, 72, value, radix, uppercase) |
| return String._fromWellFormedCodeUnitSequence( |
| UTF8.self, |
| input: UnsafeBufferPointer( |
| start: bufferUTF8Ptr, count: Int(actualLength))) |
| } |
| } |
| } |
| |
| @warn_unused_result |
| @_silgen_name("swift_uint64ToString") |
| func _uint64ToStringImpl( |
| buffer: UnsafeMutablePointer<UTF8.CodeUnit>, |
| _ bufferLength: UInt, _ value: UInt64, _ radix: Int64, _ uppercase: Bool |
| ) -> UInt |
| |
| @warn_unused_result |
| public // @testable |
| func _uint64ToString( |
| value: UInt64, radix: Int64 = 10, uppercase: Bool = false |
| ) -> String { |
| if radix >= 10 { |
| var buffer = _Buffer32() |
| return withUnsafeMutablePointer(&buffer) { |
| (bufferPtr) in |
| let bufferUTF8Ptr = UnsafeMutablePointer<UTF8.CodeUnit>(bufferPtr) |
| let actualLength = |
| _uint64ToStringImpl(bufferUTF8Ptr, 32, value, radix, uppercase) |
| return String._fromWellFormedCodeUnitSequence( |
| UTF8.self, |
| input: UnsafeBufferPointer( |
| start: bufferUTF8Ptr, count: Int(actualLength))) |
| } |
| } else { |
| var buffer = _Buffer72() |
| return withUnsafeMutablePointer(&buffer) { |
| (bufferPtr) in |
| let bufferUTF8Ptr = UnsafeMutablePointer<UTF8.CodeUnit>(bufferPtr) |
| let actualLength = |
| _uint64ToStringImpl(bufferUTF8Ptr, 72, value, radix, uppercase) |
| return String._fromWellFormedCodeUnitSequence( |
| UTF8.self, |
| input: UnsafeBufferPointer( |
| start: bufferUTF8Ptr, count: Int(actualLength))) |
| } |
| } |
| } |
| |
| @warn_unused_result |
| func _rawPointerToString(value: Builtin.RawPointer) -> String { |
| var result = _uint64ToString( |
| UInt64(unsafeBitCast(value, UInt.self)), radix: 16, uppercase: false) |
| for _ in 0..<(2 * sizeof(Builtin.RawPointer) - result.utf16.count) { |
| result = "0" + result |
| } |
| return "0x" + result |
| } |
| |
| #if _runtime(_ObjC) |
| // At runtime, these classes are derived from `_SwiftNativeNSXXXBase`, |
| // which are derived from `NSXXX`. |
| // |
| // The @swift_native_objc_runtime_base attribute |
| // allows us to subclass an Objective-C class and still use the fast Swift |
| // memory allocator. |
| |
| @objc @_swift_native_objc_runtime_base(_SwiftNativeNSArrayBase) |
| class _SwiftNativeNSArray {} |
| |
| @objc @_swift_native_objc_runtime_base(_SwiftNativeNSDictionaryBase) |
| class _SwiftNativeNSDictionary {} |
| |
| @objc @_swift_native_objc_runtime_base(_SwiftNativeNSSetBase) |
| class _SwiftNativeNSSet {} |
| |
| @objc @_swift_native_objc_runtime_base(_SwiftNativeNSEnumeratorBase) |
| class _SwiftNativeNSEnumerator {} |
| |
| //===----------------------------------------------------------------------===// |
| // Support for reliable testing of the return-autoreleased optimization |
| //===----------------------------------------------------------------------===// |
| |
| @objc internal class _stdlib_ReturnAutoreleasedDummy { |
| // Use 'dynamic' to force Objective-C dispatch, which uses the |
| // return-autoreleased call sequence. |
| @objc dynamic func returnsAutoreleased(x: AnyObject) -> AnyObject { |
| return x |
| } |
| |
| // Use 'dynamic' to prevent this call to be duplicated into other modules. |
| @objc dynamic func initializeReturnAutoreleased() { |
| // On x86_64 it is sufficient to perform one cycle of return-autoreleased |
| // call sequence in order to initialize all required PLT entries. |
| self.returnsAutoreleased(self) |
| } |
| } |
| |
| /// This function ensures that the return-autoreleased optimization works. |
| /// |
| /// On some platforms (for example, x86_64), the first call to |
| /// `objc_autoreleaseReturnValue` will always autorelease because it would fail |
| /// to verify the instruction sequence in the caller. On x86_64 certain PLT |
| /// entries would be still pointing to the resolver function, and sniffing |
| /// the call sequence would fail. |
| /// |
| /// This code should live in the core stdlib dylib because PLT tables are |
| /// separate for each dylib. |
| /// |
| /// Call this function in a fresh autorelease pool. |
| public func _stdlib_initializeReturnAutoreleased() { |
| // _stdlib_initializeReturnAutoreleasedImpl() |
| #if arch(x86_64) |
| _stdlib_ReturnAutoreleasedDummy().initializeReturnAutoreleased() |
| #endif |
| } |
| #else |
| |
| class _SwiftNativeNSArray {} |
| class _SwiftNativeNSDictionary {} |
| class _SwiftNativeNSSet {} |
| |
| #endif |