//===----------------------------------------------------------------------===// // // 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 https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// import SwiftShims // Definitions that make elements of Builtin usable in real code // without gobs of boilerplate. @available(*, unavailable, message: "use MemoryLayout.size instead.") public func sizeof(_:T.Type) -> Int { Builtin.unreachable() } @available(*, unavailable, renamed: "MemoryLayout.size(ofValue:)") public func sizeofValue(_:T) -> Int { Builtin.unreachable() } @available(*, unavailable, message: "use MemoryLayout.alignment instead.") public func alignof(_:T.Type) -> Int { Builtin.unreachable() } @available(*, unavailable, renamed: "MemoryLayout.alignment(ofValue:)") public func alignofValue(_:T) -> Int { Builtin.unreachable() } @available(*, unavailable, message: "use MemoryLayout.stride instead.") public func strideof(_:T.Type) -> Int { Builtin.unreachable() } @available(*, unavailable, renamed: "MemoryLayout.stride(ofValue:)") public func strideofValue(_:T) -> Int { Builtin.unreachable() } // This function is the implementation of the `_roundUp` overload set. It is // marked `@inline(__always)` to make primary `_roundUp` entry points seem // cheap enough for the inliner. @_versioned @inline(__always) internal func _roundUpImpl(_ offset: UInt, toAlignment alignment: Int) -> UInt { _sanityCheck(alignment > 0) _sanityCheck(_isPowerOf2(alignment)) // Note, given that offset is >= 0, and alignment > 0, we don't // need to underflow check the -1, as it can never underflow. let x = offset + UInt(bitPattern: alignment) &- 1 // Note, as alignment is a power of 2, we'll use masking to efficiently // get the aligned value return x & ~(UInt(bitPattern: alignment) &- 1) } @_versioned internal func _roundUp(_ offset: UInt, toAlignment alignment: Int) -> UInt { return _roundUpImpl(offset, toAlignment: alignment) } @_versioned internal func _roundUp(_ offset: Int, toAlignment alignment: Int) -> Int { _sanityCheck(offset >= 0) return Int(_roundUpImpl(UInt(bitPattern: offset), toAlignment: alignment)) } /// Returns a tri-state of 0 = no, 1 = yes, 2 = maybe. @_transparent public // @testable func _canBeClass(_: T.Type) -> Int8 { return Int8(Builtin.canBeClass(T.self)) } /// Returns the bits of `x`, interpreted as having type `U`. /// /// - Warning: Breaks the guarantees of Swift's type system; use /// with extreme care. There's almost always a better way to do /// anything. /// @_transparent public func unsafeBitCast(_ x: T, to: U.Type) -> U { _precondition(MemoryLayout.size == MemoryLayout.size, "can't unsafeBitCast between types of different sizes") return Builtin.reinterpretCast(x) } /// `unsafeBitCast` something to `AnyObject`. @_transparent internal func _reinterpretCastToAnyObject(_ x: T) -> AnyObject { return unsafeBitCast(x, to: AnyObject.self) } @_transparent func == (lhs: Builtin.NativeObject, rhs: Builtin.NativeObject) -> Bool { return unsafeBitCast(lhs, to: Int.self) == unsafeBitCast(rhs, to: Int.self) } @_transparent func != (lhs: Builtin.NativeObject, rhs: Builtin.NativeObject) -> Bool { return !(lhs == rhs) } @_transparent func == (lhs: Builtin.RawPointer, rhs: Builtin.RawPointer) -> Bool { return unsafeBitCast(lhs, to: Int.self) == unsafeBitCast(rhs, to: Int.self) } @_transparent func != (lhs: Builtin.RawPointer, rhs: Builtin.RawPointer) -> Bool { return !(lhs == rhs) } /// Returns `true` iff `t0` is identical to `t1`; i.e. if they are both /// `nil` or they both represent the same type. public func == (t0: Any.Type?, t1: Any.Type?) -> Bool { return unsafeBitCast(t0, to: Int.self) == unsafeBitCast(t1, to: Int.self) } /// Returns `false` iff `t0` is identical to `t1`; i.e. if they are both /// `nil` or they both represent the same type. public func != (t0: Any.Type?, t1: Any.Type?) -> Bool { return !(t0 == t1) } /// Tell the optimizer that this code is unreachable if condition is /// known at compile-time to be true. If condition is false, or true /// but not a compile-time constant, this call has no effect. @_transparent internal func _unreachable(_ condition: Bool = true) { if condition { // FIXME: use a parameterized version of Builtin.unreachable when // is closed. Builtin.unreachable() } } /// Tell the optimizer that this code is unreachable if this builtin is /// reachable after constant folding build configuration builtins. @_versioned @_transparent internal func _conditionallyUnreachable() -> Never { Builtin.conditionallyUnreachable() } @_versioned @_silgen_name("_swift_isClassOrObjCExistentialType") func _swift_isClassOrObjCExistentialType(_ x: T.Type) -> Bool /// Returns `true` iff `T` is a class type or an `@objc` existential such as /// `AnyObject`. @_versioned @inline(__always) internal func _isClassOrObjCExistential(_ x: T.Type) -> Bool { switch _canBeClass(x) { // Is not a class. case 0: return false // Is a class. case 1: return true // Maybe a class. default: return _swift_isClassOrObjCExistentialType(x) } } /// Returns an `UnsafePointer` to the storage used for `object`. There's /// not much you can do with this other than use it to identify the /// object. @available(*, unavailable, message: "Removed in Swift 3. Use Unmanaged.passUnretained(x).toOpaque() instead.") public func unsafeAddress(of object: AnyObject) -> UnsafeRawPointer { Builtin.unreachable() } @available(*, unavailable, message: "Removed in Swift 3. Use Unmanaged.passUnretained(x).toOpaque() instead.") public func unsafeAddressOf(_ object: AnyObject) -> UnsafeRawPointer { Builtin.unreachable() } /// Converts a reference of type `T` to a reference of type `U` after /// unwrapping one level of Optional. /// /// Unwrapped `T` and `U` must be convertible to AnyObject. They may /// be either a class or a class protocol. Either T, U, or both may be /// optional references. @_transparent public func _unsafeReferenceCast(_ x: T, to: U.Type) -> U { return Builtin.castReference(x) } /// - returns: `x as T`. /// /// - Precondition: `x is T`. In particular, in -O builds, no test is /// performed to ensure that `x` actually has dynamic type `T`. /// /// - Warning: Trades safety for performance. Use `unsafeDowncast` /// only when `x as T` has proven to be a performance problem and you /// are confident that, always, `x is T`. It is better than an /// `unsafeBitCast` because it's more restrictive, and because /// checking is still performed in debug builds. @_transparent public func unsafeDowncast(_ x: AnyObject, to: T.Type) -> T { _debugPrecondition(x is T, "invalid unsafeDowncast") return Builtin.castReference(x) } @inline(__always) public func _getUnsafePointerToStoredProperties(_ x: AnyObject) -> UnsafeMutableRawPointer { let storedPropertyOffset = _roundUp( MemoryLayout<_HeapObject>.size, toAlignment: MemoryLayout>.alignment) return UnsafeMutableRawPointer(Builtin.bridgeToRawPointer(x)) + storedPropertyOffset } //===----------------------------------------------------------------------===// // Branch hints //===----------------------------------------------------------------------===// // Use @_semantics to indicate that the optimizer recognizes the // semantics of these function calls. This won't be necessary with // mandatory generic inlining. @_versioned @_transparent @_semantics("branchhint") internal func _branchHint(_ actual: Bool, expected: Bool) -> Bool { return Bool(Builtin.int_expect_Int1(actual._value, expected._value)) } /// Optimizer hint that `x` is expected to be `true`. @_transparent @_semantics("fastpath") public func _fastPath(_ x: Bool) -> Bool { return _branchHint(x, expected: true) } /// Optimizer hint that `x` is expected to be `false`. @_transparent @_semantics("slowpath") public func _slowPath(_ x: Bool) -> Bool { return _branchHint(x, expected: false) } /// Optimizer hint that the code where this function is called is on the fast /// path. @_transparent public func _onFastPath() { Builtin.onFastPath() } //===--- Runtime shim wrappers --------------------------------------------===// /// Returns `true` iff the class indicated by `theClass` uses native /// Swift reference-counting. #if _runtime(_ObjC) // Declare it here instead of RuntimeShims.h, because we need to specify // the type of argument to be AnyClass. This is currently not possible // when using RuntimeShims.h @_versioned @_silgen_name("swift_objc_class_usesNativeSwiftReferenceCounting") func _usesNativeSwiftReferenceCounting(_ theClass: AnyClass) -> Bool #else @_versioned @inline(__always) func _usesNativeSwiftReferenceCounting(_ theClass: AnyClass) -> Bool { return true } #endif @_silgen_name("swift_class_getInstanceExtents") func swift_class_getInstanceExtents(_ theClass: AnyClass) -> (negative: UInt, positive: UInt) @_silgen_name("swift_objc_class_unknownGetInstanceExtents") func swift_objc_class_unknownGetInstanceExtents(_ theClass: AnyClass) -> (negative: UInt, positive: UInt) /// - Returns: @inline(__always) internal func _class_getInstancePositiveExtentSize(_ theClass: AnyClass) -> Int { #if _runtime(_ObjC) return Int(swift_objc_class_unknownGetInstanceExtents(theClass).positive) #else return Int(swift_class_getInstanceExtents(theClass).positive) #endif } //===--- Builtin.BridgeObject ---------------------------------------------===// #if arch(i386) || arch(arm) @_versioned internal var _objectPointerSpareBits: UInt { @inline(__always) get { return 0x0000_0003 } } @_versioned internal var _objectPointerIsObjCBit: UInt { @inline(__always) get { return 0x0000_0002 } } @_versioned internal var _objectPointerLowSpareBitShift: UInt { @inline(__always) get { return 0 } } @_versioned internal var _objCTaggedPointerBits: UInt { @inline(__always) get { return 0 } } #elseif arch(x86_64) @_versioned internal var _objectPointerSpareBits: UInt { @inline(__always) get { return 0x7F00_0000_0000_0006 } } @_versioned internal var _objectPointerIsObjCBit: UInt { @inline(__always) get { return 0x4000_0000_0000_0000 } } @_versioned internal var _objectPointerLowSpareBitShift: UInt { @inline(__always) get { return 1 } } @_versioned internal var _objCTaggedPointerBits: UInt { @inline(__always) get { return 0x8000_0000_0000_0001 } } #elseif arch(arm64) @_versioned internal var _objectPointerSpareBits: UInt { @inline(__always) get { return 0x7F00_0000_0000_0007 } } @_versioned internal var _objectPointerIsObjCBit: UInt { @inline(__always) get { return 0x4000_0000_0000_0000 } } @_versioned internal var _objectPointerLowSpareBitShift: UInt { @inline(__always) get { return 0 } } @_versioned internal var _objCTaggedPointerBits: UInt { @inline(__always) get { return 0x8000_0000_0000_0000 } } #elseif arch(powerpc64) || arch(powerpc64le) @_versioned internal var _objectPointerSpareBits: UInt { @inline(__always) get { return 0x0000_0000_0000_0007 } } @_versioned internal var _objectPointerIsObjCBit: UInt { @inline(__always) get { return 0x0000_0000_0000_0002 } } @_versioned internal var _objectPointerLowSpareBitShift: UInt { @inline(__always) get { return 0 } } @_versioned internal var _objCTaggedPointerBits: UInt { @inline(__always) get { return 0 } } #elseif arch(s390x) internal var _objectPointerSpareBits: UInt { @inline(__always) get { return 0x0000_0000_0000_0007 } } internal var _objectPointerIsObjCBit: UInt { @inline(__always) get { return 0x0000_0000_0000_0002 } } internal var _objectPointerLowSpareBitShift: UInt { @inline(__always) get { return 0 } } internal var _objCTaggedPointerBits: UInt { @inline(__always) get { return 0 } } #endif /// Extract the raw bits of `x`. @_versioned @inline(__always) internal func _bitPattern(_ x: Builtin.BridgeObject) -> UInt { return UInt(Builtin.castBitPatternFromBridgeObject(x)) } /// Extract the raw spare bits of `x`. @_versioned @inline(__always) internal func _nonPointerBits(_ x: Builtin.BridgeObject) -> UInt { return _bitPattern(x) & _objectPointerSpareBits } @_versioned @inline(__always) internal func _isObjCTaggedPointer(_ x: AnyObject) -> Bool { return (Builtin.reinterpretCast(x) & _objCTaggedPointerBits) != 0 } /// Create a `BridgeObject` around the given `nativeObject` with the /// given spare bits. /// /// Reference-counting and other operations on this /// object will have access to the knowledge that it is native. /// /// - Precondition: `bits & _objectPointerIsObjCBit == 0`, /// `bits & _objectPointerSpareBits == bits`. @_versioned @inline(__always) internal func _makeNativeBridgeObject( _ nativeObject: AnyObject, _ bits: UInt ) -> Builtin.BridgeObject { _sanityCheck( (bits & _objectPointerIsObjCBit) == 0, "BridgeObject is treated as non-native when ObjC bit is set" ) return _makeBridgeObject(nativeObject, bits) } /// Create a `BridgeObject` around the given `objCObject`. @inline(__always) public // @testable func _makeObjCBridgeObject( _ objCObject: AnyObject ) -> Builtin.BridgeObject { return _makeBridgeObject( objCObject, _isObjCTaggedPointer(objCObject) ? 0 : _objectPointerIsObjCBit) } /// Create a `BridgeObject` around the given `object` with the /// given spare bits. /// /// - Precondition: /// /// 1. `bits & _objectPointerSpareBits == bits` /// 2. if `object` is a tagged pointer, `bits == 0`. Otherwise, /// `object` is either a native object, or `bits == /// _objectPointerIsObjCBit`. @_versioned @inline(__always) internal func _makeBridgeObject( _ object: AnyObject, _ bits: UInt ) -> Builtin.BridgeObject { _sanityCheck(!_isObjCTaggedPointer(object) || bits == 0, "Tagged pointers cannot be combined with bits") _sanityCheck( _isObjCTaggedPointer(object) || _usesNativeSwiftReferenceCounting(type(of: object)) || bits == _objectPointerIsObjCBit, "All spare bits must be set in non-native, non-tagged bridge objects" ) _sanityCheck( bits & _objectPointerSpareBits == bits, "Can't store non-spare bits into Builtin.BridgeObject") return Builtin.castToBridgeObject( object, bits._builtinWordValue ) } @_versioned @_silgen_name("_swift_class_getSuperclass") internal func _swift_class_getSuperclass(_ t: AnyClass) -> AnyClass? /// Returns the superclass of `t`, if any. The result is `nil` if `t` is /// a root class or class protocol. @inline(__always) public // @testable func _getSuperclass(_ t: AnyClass) -> AnyClass? { return _swift_class_getSuperclass(t) } /// Returns the superclass of `t`, if any. The result is `nil` if `t` is /// not a class, is a root class, or is a class protocol. @inline(__always) public // @testable func _getSuperclass(_ t: Any.Type) -> AnyClass? { return (t as? AnyClass).flatMap { _getSuperclass($0) } } //===--- Builtin.IsUnique -------------------------------------------------===// // _isUnique functions must take an inout object because they rely on // Builtin.isUnique which requires an inout reference to preserve // source-level copies in the presence of ARC optimization. // // Taking an inout object makes sense for two additional reasons: // // 1. You should only call it when about to mutate the object. // Doing so otherwise implies a race condition if the buffer is // shared across threads. // // 2. When it is not an inout function, self is passed by // value... thus bumping the reference count and disturbing the // result we are trying to observe, Dr. Heisenberg! // // _isUnique and _isUniquePinned cannot be made public or the compiler // will attempt to generate generic code for the transparent function // and type checking will fail. /// Returns `true` if `object` is uniquely referenced. @_versioned @_transparent internal func _isUnique(_ object: inout T) -> Bool { return Bool(Builtin.isUnique(&object)) } /// Returns `true` if `object` is uniquely referenced or pinned. @_versioned @_transparent internal func _isUniqueOrPinned(_ object: inout T) -> Bool { return Bool(Builtin.isUniqueOrPinned(&object)) } /// Returns `true` if `object` is uniquely referenced. /// This provides sanity checks on top of the Builtin. @_transparent public // @testable func _isUnique_native(_ object: inout T) -> Bool { // This could be a bridge object, single payload enum, or plain old // reference. Any case it's non pointer bits must be zero, so // force cast it to BridgeObject and check the spare bits. _sanityCheck( (_bitPattern(Builtin.reinterpretCast(object)) & _objectPointerSpareBits) == 0) _sanityCheck(_usesNativeSwiftReferenceCounting( type(of: Builtin.reinterpretCast(object) as AnyObject))) return Bool(Builtin.isUnique_native(&object)) } /// Returns `true` if `object` is uniquely referenced or pinned. /// This provides sanity checks on top of the Builtin. @_transparent public // @testable func _isUniqueOrPinned_native(_ object: inout T) -> Bool { // This could be a bridge object, single payload enum, or plain old // reference. Any case it's non pointer bits must be zero. _sanityCheck( (_bitPattern(Builtin.reinterpretCast(object)) & _objectPointerSpareBits) == 0) _sanityCheck(_usesNativeSwiftReferenceCounting( type(of: Builtin.reinterpretCast(object) as AnyObject))) return Bool(Builtin.isUniqueOrPinned_native(&object)) } /// Returns `true` if type is a POD type. A POD type is a type that does not /// require any special handling on copying or destruction. @_transparent public // @testable func _isPOD(_ type: T.Type) -> Bool { return Bool(Builtin.ispod(type)) } /// Returns `true` if type is nominally an Optional type. @_transparent public // @testable func _isOptional(_ type: T.Type) -> Bool { return Bool(Builtin.isOptional(type)) } @available(*, unavailable, message: "Removed in Swift 3. Please use Optional.unsafelyUnwrapped instead.") public func unsafeUnwrap(_ nonEmpty: T?) -> T { Builtin.unreachable() } /// Extract an object reference from an Any known to contain an object. internal func _unsafeDowncastToAnyObject(fromAny any: Any) -> AnyObject { _sanityCheck(type(of: any) is AnyObject.Type || type(of: any) is AnyObject.Protocol, "Any expected to contain object reference") // With a SIL instruction, we could more efficiently grab the object reference // out of the Any's inline storage. // On Linux, bridging isn't supported, so this is a force cast. #if _runtime(_ObjC) return any as AnyObject #else return any as! AnyObject #endif }