Files
swift-mirror/stdlib/public/core/BridgeStorage.swift
Slava Pestov d65d1d25f9 Sema: Diagnostics for @_inlineable, @_versioned and Swift 4 default arguments model
Piggybacks some resilience diagnostics onto the availability
checking code.

Public and versioned functions with inlineable bodies can only
reference other public and internal entities, since the SIL code
for the function body is serialized and stored as part of the
module.

This includes @_transparent functions, @_inlineable functions,
accessors for @_inlineable storage, @inline(__always) functions,
and in Swift 4 mode, default argument expressions.

The new checks are a source-breaking change, however we don't
guarantee source compatibility for underscored attributes.

The new ABI and tests for the default argument model will come in
subsequent commits.
2017-01-09 16:59:13 -08:00

156 lines
4.4 KiB
Swift

//===--- BridgeStorage.swift - Discriminated storage for bridged types ----===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 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
//
//===----------------------------------------------------------------------===//
//
// Types that are bridged to Objective-C need to manage an object
// that may be either some native class or the @objc Cocoa
// equivalent. _BridgeStorage discriminates between these two
// possibilities and stores a few extra bits when the stored type is
// native. It is assumed that the @objc class instance may in fact
// be a tagged pointer, and thus no extra bits may be available.
//
//===----------------------------------------------------------------------===//
import SwiftShims
@_fixed_layout
public // @testable
struct _BridgeStorage<
NativeClass: AnyObject, ObjCClass: AnyObject
> {
public // @testable
typealias Native = NativeClass
public // @testable
typealias ObjC = ObjCClass
@inline(__always)
public // @testable
init(native: Native, bits: Int) {
_sanityCheck(_usesNativeSwiftReferenceCounting(NativeClass.self))
// More bits are available on some platforms, but it's not portable
_sanityCheck(0...1 ~= bits,
"BridgeStorage can't store bits outside the range 0...1")
rawValue = _makeNativeBridgeObject(
native, UInt(bits) << _objectPointerLowSpareBitShift)
}
@inline(__always)
public // @testable
init(objC: ObjC) {
_sanityCheck(_usesNativeSwiftReferenceCounting(NativeClass.self))
rawValue = _makeObjCBridgeObject(objC)
}
@inline(__always)
public // @testable
init(native: Native) {
_sanityCheck(_usesNativeSwiftReferenceCounting(NativeClass.self))
rawValue = Builtin.reinterpretCast(native)
}
public // @testable
var spareBits: Int {
@inline(__always) get {
_sanityCheck(isNative)
return Int(
_nonPointerBits(rawValue) >> _objectPointerLowSpareBitShift)
}
}
@inline(__always)
public // @testable
mutating func isUniquelyReferencedNative() -> Bool {
return _isUnique(&rawValue)
}
@inline(__always)
public // @testable
mutating func isUniquelyReferencedOrPinnedNative() -> Bool {
return _isUniqueOrPinned(&rawValue)
}
public // @testable
var isNative: Bool {
@inline(__always) get {
return (_bitPattern(rawValue) &
(_objCTaggedPointerBits | _objectPointerIsObjCBit)) == 0
}
}
@inline(__always)
public // @testable
func isNativeWithClearedSpareBits(_ bits: Int) -> Bool {
return (_bitPattern(rawValue) &
(_objCTaggedPointerBits | _objectPointerIsObjCBit |
(UInt(bits)) << _objectPointerLowSpareBitShift)) == 0
}
public // @testable
var isObjC: Bool {
@inline(__always) get {
return !isNative
}
}
public // @testable
var nativeInstance: Native {
@inline(__always) get {
_sanityCheck(isNative)
return Builtin.castReferenceFromBridgeObject(rawValue)
}
}
public // @testable
var nativeInstance_noSpareBits: Native {
@inline(__always) get {
_sanityCheck(isNative)
_sanityCheck(_nonPointerBits(rawValue) == 0)
return Builtin.reinterpretCast(rawValue)
}
}
@inline(__always)
public // @testable
mutating func isUniquelyReferenced_native_noSpareBits() -> Bool {
_sanityCheck(isNative)
return _isUnique_native(&rawValue)
}
@inline(__always)
public // @testable
mutating func isUniquelyReferencedOrPinned_native_noSpareBits() -> Bool {
_sanityCheck(isNative)
return _isUniqueOrPinned_native(&rawValue)
}
public // @testable
var objCInstance: ObjC {
@inline(__always) get {
_sanityCheck(isObjC)
return Builtin.castReferenceFromBridgeObject(rawValue)
}
}
//===--- private --------------------------------------------------------===//
internal var _isTagged: Bool {
@inline(__always) get {
return (_bitPattern(rawValue) & _objCTaggedPointerBits) != 0
}
}
// rawValue is passed inout to _isUnique. Although its value
// is unchanged, it must appear mutable to the optimizer.
@_versioned
internal var rawValue: Builtin.BridgeObject
}