mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Use @c instead of @_cdecl in the Embedded Swift runtime
This change moves us toward the official feature, and eliminates the extra level of "thunk" that was implied by `@_cdecl`. Amusingly, this trips up the LLVM-level ARC optimizations, because we are trying to perform ARC optimizations within the retain/release runtime functions. Teach those optimization passes to leave swift_retainN et al alone.
This commit is contained in:
@@ -403,6 +403,11 @@ void SwiftARCContract::getAnalysisUsage(llvm::AnalysisUsage &AU) const {
|
||||
llvm::PreservedAnalyses
|
||||
SwiftARCContractPass::run(llvm::Function &F,
|
||||
llvm::FunctionAnalysisManager &AM) {
|
||||
// Don't touch those functions that implement reference counting in the
|
||||
// runtime.
|
||||
if (!allowArcOptimizations(F.getName()))
|
||||
return PreservedAnalyses::all();
|
||||
|
||||
bool changed = SwiftARCContractImpl(F).run();
|
||||
if (!changed)
|
||||
return PreservedAnalyses::all();
|
||||
|
||||
@@ -1015,6 +1015,12 @@ void SwiftARCOpt::getAnalysisUsage(llvm::AnalysisUsage &AU) const {
|
||||
|
||||
static bool runSwiftARCOpts(Function &F, SwiftRCIdentity &RC) {
|
||||
bool Changed = false;
|
||||
|
||||
// Don't touch those functions that implement reference counting in the
|
||||
// runtime.
|
||||
if (!allowArcOptimizations(F.getName()))
|
||||
return Changed;
|
||||
|
||||
ARCEntryPointBuilder B(F);
|
||||
|
||||
// First thing: canonicalize swift_retain and similar calls so that nothing
|
||||
|
||||
@@ -26,6 +26,62 @@ enum RT_Kind {
|
||||
#include "LLVMSwift.def"
|
||||
};
|
||||
|
||||
inline RT_Kind classifyFunctionName(StringRef name) {
|
||||
return llvm::StringSwitch<RT_Kind>(name)
|
||||
#define SWIFT_FUNC(Name, MemBehavior, TextualName) \
|
||||
.Case("swift_" #TextualName, RT_ ## Name)
|
||||
#define SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC(Name, MemBehavior, TextualName) \
|
||||
.Case("__swift_" #TextualName, RT_ ## Name)
|
||||
#include "LLVMSwift.def"
|
||||
|
||||
// Identify "Client" versions of reference counting entry points.
|
||||
#define SWIFT_FUNC(Name, MemBehavior, TextualName) \
|
||||
.Case("swift_" #TextualName "Client", RT_ ## Name)
|
||||
#define SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC(Name, MemBehavior, TextualName) \
|
||||
.Case("__swift_" #TextualName "Client", RT_ ## Name)
|
||||
#include "LLVMSwift.def"
|
||||
|
||||
// Support non-atomic versions of reference counting entry points.
|
||||
#define SWIFT_FUNC(Name, MemBehavior, TextualName) \
|
||||
.Case("swift_nonatomic_" #TextualName, RT_ ## Name)
|
||||
#define OBJC_FUNC(Name, MemBehavior, TextualName) \
|
||||
.Case("objc_nonatomic_" #TextualName, RT_ ## Name)
|
||||
#define SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC(Name, MemBehavior, TextualName)
|
||||
#include "LLVMSwift.def"
|
||||
|
||||
.Default(RT_Unknown);
|
||||
}
|
||||
|
||||
/// Whether to allow ARC optimizations for a function with the given name.
|
||||
inline bool allowArcOptimizations(StringRef name) {
|
||||
switch (classifyFunctionName(name)) {
|
||||
case RT_UnknownObjectRetainN:
|
||||
case RT_BridgeRetainN:
|
||||
case RT_RetainN:
|
||||
case RT_UnknownObjectReleaseN:
|
||||
case RT_BridgeReleaseN:
|
||||
case RT_ReleaseN:
|
||||
case RT_UnknownObjectRetain:
|
||||
case RT_UnknownObjectRelease:
|
||||
case RT_Retain:
|
||||
case RT_ObjCRetain:
|
||||
case RT_ObjCRelease:
|
||||
case RT_RetainUnowned:
|
||||
case RT_Release:
|
||||
case RT_BridgeRetain:
|
||||
case RT_BridgeRelease:
|
||||
return false;
|
||||
|
||||
case RT_Unknown:
|
||||
case RT_NoMemoryAccessed:
|
||||
case RT_CheckUnowned:
|
||||
case RT_AllocObject:
|
||||
case RT_FixLifetime:
|
||||
case RT_EndBorrow:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// Take a look at the specified instruction and classify it into what kind of
|
||||
/// runtime entrypoint it is, if any.
|
||||
inline RT_Kind classifyInstruction(const llvm::Instruction &I) {
|
||||
@@ -57,29 +113,7 @@ inline RT_Kind classifyInstruction(const llvm::Instruction &I) {
|
||||
if (F == nullptr)
|
||||
return RT_Unknown;
|
||||
|
||||
return llvm::StringSwitch<RT_Kind>(F->getName())
|
||||
#define SWIFT_FUNC(Name, MemBehavior, TextualName) \
|
||||
.Case("swift_" #TextualName, RT_ ## Name)
|
||||
#define SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC(Name, MemBehavior, TextualName) \
|
||||
.Case("__swift_" #TextualName, RT_ ## Name)
|
||||
#include "LLVMSwift.def"
|
||||
|
||||
// Identify "Client" versions of reference counting entry points.
|
||||
#define SWIFT_FUNC(Name, MemBehavior, TextualName) \
|
||||
.Case("swift_" #TextualName "Client", RT_ ## Name)
|
||||
#define SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC(Name, MemBehavior, TextualName) \
|
||||
.Case("__swift_" #TextualName "Client", RT_ ## Name)
|
||||
#include "LLVMSwift.def"
|
||||
|
||||
// Support non-atomic versions of reference counting entry points.
|
||||
#define SWIFT_FUNC(Name, MemBehavior, TextualName) \
|
||||
.Case("swift_nonatomic_" #TextualName, RT_ ## Name)
|
||||
#define OBJC_FUNC(Name, MemBehavior, TextualName) \
|
||||
.Case("objc_nonatomic_" #TextualName, RT_ ## Name)
|
||||
#define SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC(Name, MemBehavior, TextualName)
|
||||
#include "LLVMSwift.def"
|
||||
|
||||
.Default(RT_Unknown);
|
||||
return classifyFunctionName(F->getName());
|
||||
}
|
||||
|
||||
} // end namespace swift
|
||||
|
||||
@@ -149,14 +149,14 @@ func alignedAlloc(size: Int, alignment: Int) -> UnsafeMutableRawPointer? {
|
||||
return unsafe r
|
||||
}
|
||||
|
||||
@_cdecl("swift_coroFrameAlloc")
|
||||
@c
|
||||
public func swift_coroFrameAlloc(_ size: Int, _ type: UInt) -> UnsafeMutableRawPointer? {
|
||||
return unsafe alignedAlloc(
|
||||
size: size,
|
||||
alignment: _swift_MinAllocationAlignment)
|
||||
}
|
||||
|
||||
@_cdecl("swift_slowAlloc")
|
||||
@c
|
||||
public func swift_slowAlloc(_ size: Int, _ alignMask: Int) -> UnsafeMutableRawPointer? {
|
||||
let alignment: Int
|
||||
if alignMask == -1 {
|
||||
@@ -167,12 +167,12 @@ public func swift_slowAlloc(_ size: Int, _ alignMask: Int) -> UnsafeMutableRawPo
|
||||
return unsafe alignedAlloc(size: size, alignment: alignment)
|
||||
}
|
||||
|
||||
@_cdecl("swift_slowDealloc")
|
||||
@c
|
||||
public func swift_slowDealloc(_ ptr: UnsafeMutableRawPointer, _ size: Int, _ alignMask: Int) {
|
||||
unsafe free(ptr)
|
||||
}
|
||||
|
||||
@_cdecl("swift_allocObject")
|
||||
@c
|
||||
public func swift_allocObject(metadata: Builtin.RawPointer, requiredSize: Int, requiredAlignmentMask: Int) -> Builtin.RawPointer {
|
||||
return unsafe swift_allocObject(metadata: UnsafeMutablePointer<ClassMetadata>(metadata), requiredSize: requiredSize, requiredAlignmentMask: requiredAlignmentMask)._rawValue
|
||||
}
|
||||
@@ -185,7 +185,7 @@ func swift_allocObject(metadata: UnsafeMutablePointer<ClassMetadata>, requiredSi
|
||||
return unsafe object
|
||||
}
|
||||
|
||||
@_cdecl("swift_deallocUninitializedObject")
|
||||
@c
|
||||
public func swift_deallocUninitializedObject(object: Builtin.RawPointer, allocatedSize: Int, allocatedAlignMask: Int) {
|
||||
unsafe swift_deallocObject(
|
||||
object: UnsafeMutablePointer<HeapObject>(object),
|
||||
@@ -193,7 +193,7 @@ public func swift_deallocUninitializedObject(object: Builtin.RawPointer, allocat
|
||||
allocatedAlignMask: allocatedAlignMask)
|
||||
}
|
||||
|
||||
@_cdecl("swift_deallocObject")
|
||||
@c
|
||||
public func swift_deallocObject(object: Builtin.RawPointer, allocatedSize: Int, allocatedAlignMask: Int) {
|
||||
unsafe swift_deallocObject(object: UnsafeMutablePointer<HeapObject>(object), allocatedSize: allocatedSize, allocatedAlignMask: allocatedAlignMask)
|
||||
}
|
||||
@@ -202,7 +202,7 @@ func swift_deallocObject(object: UnsafeMutablePointer<HeapObject>, allocatedSize
|
||||
unsafe free(UnsafeMutableRawPointer(object))
|
||||
}
|
||||
|
||||
@_cdecl("swift_deallocClassInstance")
|
||||
@c
|
||||
public func swift_deallocClassInstance(object: Builtin.RawPointer, allocatedSize: Int, allocatedAlignMask: Int) {
|
||||
unsafe swift_deallocClassInstance(object: UnsafeMutablePointer<HeapObject>(object), allocatedSize: allocatedSize, allocatedAlignMask: allocatedAlignMask)
|
||||
}
|
||||
@@ -215,7 +215,7 @@ func swift_deallocClassInstance(object: UnsafeMutablePointer<HeapObject>, alloca
|
||||
unsafe free(UnsafeMutableRawPointer(object))
|
||||
}
|
||||
|
||||
@_cdecl("swift_deallocPartialClassInstance")
|
||||
@c
|
||||
public func swift_deallocPartialClassInstance(object: Builtin.RawPointer, metadata: Builtin.RawPointer, allocatedSize: Int, allocatedAlignMask: Int) {
|
||||
unsafe swift_deallocPartialClassInstance(object: UnsafeMutablePointer<HeapObject>(object), metadata: UnsafeMutablePointer<ClassMetadata>(metadata), allocatedSize: allocatedSize, allocatedAlignMask: allocatedAlignMask)
|
||||
}
|
||||
@@ -229,7 +229,7 @@ func swift_deallocPartialClassInstance(object: UnsafeMutablePointer<HeapObject>,
|
||||
}
|
||||
}
|
||||
|
||||
@_cdecl("swift_initStaticObject")
|
||||
@c
|
||||
public func swift_initStaticObject(metadata: Builtin.RawPointer, object: Builtin.RawPointer) -> Builtin.RawPointer {
|
||||
return unsafe swift_initStaticObject(metadata: UnsafeMutablePointer<ClassMetadata>(metadata), object: UnsafeMutablePointer<HeapObject>(object))._rawValue
|
||||
}
|
||||
@@ -240,7 +240,7 @@ func swift_initStaticObject(metadata: UnsafeMutablePointer<ClassMetadata>, objec
|
||||
return unsafe object
|
||||
}
|
||||
|
||||
@_cdecl("swift_initStackObject")
|
||||
@c
|
||||
public func swift_initStackObject(metadata: Builtin.RawPointer, object: Builtin.RawPointer) -> Builtin.RawPointer {
|
||||
return unsafe swift_initStackObject(metadata: UnsafeMutablePointer<ClassMetadata>(metadata), object: UnsafeMutablePointer<HeapObject>(object))._rawValue
|
||||
}
|
||||
@@ -254,7 +254,7 @@ func swift_initStackObject(metadata: UnsafeMutablePointer<ClassMetadata>, object
|
||||
@unsafe
|
||||
public var _emptyBoxStorage: (Int, Int) = (/*isa*/0, /*refcount*/-1)
|
||||
|
||||
@_cdecl("swift_allocEmptyBox")
|
||||
@c
|
||||
public func swift_allocEmptyBox() -> Builtin.RawPointer {
|
||||
let box = unsafe Builtin.addressof(&_emptyBoxStorage)
|
||||
swift_retain(object: box)
|
||||
@@ -275,11 +275,11 @@ func isValidPointerForNativeRetain(object: Builtin.RawPointer) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
@_cdecl("swift_setDeallocating")
|
||||
@c
|
||||
public func swift_setDeallocating(object: Builtin.RawPointer) {
|
||||
}
|
||||
|
||||
@_cdecl("swift_dynamicCastClass")
|
||||
@c
|
||||
public func swift_dynamicCastClass(object: UnsafeMutableRawPointer, targetMetadata: UnsafeRawPointer) -> UnsafeMutableRawPointer? {
|
||||
let sourceObj = unsafe object.assumingMemoryBound(to: HeapObject.self)
|
||||
var type = unsafe _swift_embedded_get_heap_object_metadata_pointer(sourceObj).assumingMemoryBound(to: ClassMetadata.self)
|
||||
@@ -293,7 +293,7 @@ public func swift_dynamicCastClass(object: UnsafeMutableRawPointer, targetMetada
|
||||
return unsafe object
|
||||
}
|
||||
|
||||
@_cdecl("swift_dynamicCastClassUnconditional")
|
||||
@c
|
||||
public func swift_dynamicCastClassUnconditional(object: UnsafeMutableRawPointer, targetMetadata: UnsafeRawPointer,
|
||||
file: UnsafePointer<CChar>, line: CUnsignedInt, column: CUnsignedInt) -> UnsafeMutableRawPointer {
|
||||
guard let result = unsafe swift_dynamicCastClass(object: object, targetMetadata: targetMetadata) else {
|
||||
@@ -302,7 +302,7 @@ public func swift_dynamicCastClassUnconditional(object: UnsafeMutableRawPointer,
|
||||
return unsafe result
|
||||
}
|
||||
|
||||
@_cdecl("swift_isEscapingClosureAtFileLocation")
|
||||
@c
|
||||
public func swift_isEscapingClosureAtFileLocation(object: Builtin.RawPointer, filename: UnsafePointer<CChar>, filenameLength: Int32, line: Int32, column: Int32, verificationType: CUnsignedInt) -> Bool {
|
||||
let objectBits = UInt(Builtin.ptrtoint_Word(object))
|
||||
if objectBits == 0 { return false }
|
||||
@@ -313,14 +313,14 @@ public func swift_isEscapingClosureAtFileLocation(object: Builtin.RawPointer, fi
|
||||
return false
|
||||
}
|
||||
|
||||
@_cdecl("swift_isUniquelyReferenced_native")
|
||||
@c
|
||||
public func swift_isUniquelyReferenced_native(object: Builtin.RawPointer) -> Bool {
|
||||
if !isValidPointerForNativeRetain(object: object) { return false }
|
||||
|
||||
return unsafe swift_isUniquelyReferenced_nonNull_native(object: UnsafeMutablePointer<HeapObject>(object))
|
||||
}
|
||||
|
||||
@_cdecl("swift_isUniquelyReferenced_nonNull_native")
|
||||
@c
|
||||
public func swift_isUniquelyReferenced_nonNull_native(object: Builtin.RawPointer) -> Bool {
|
||||
return unsafe swift_isUniquelyReferenced_nonNull_native(object: UnsafeMutablePointer<HeapObject>(object))
|
||||
}
|
||||
@@ -330,7 +330,7 @@ func swift_isUniquelyReferenced_nonNull_native(object: UnsafeMutablePointer<Heap
|
||||
return unsafe loadAcquire(refcount) == 1
|
||||
}
|
||||
|
||||
@_cdecl("swift_retain")
|
||||
@c
|
||||
@discardableResult
|
||||
public func swift_retain(object: Builtin.RawPointer) -> Builtin.RawPointer {
|
||||
if !isValidPointerForNativeRetain(object: object) { return object }
|
||||
@@ -340,7 +340,7 @@ public func swift_retain(object: Builtin.RawPointer) -> Builtin.RawPointer {
|
||||
}
|
||||
|
||||
// Cannot use UnsafeMutablePointer<HeapObject>? directly in the function argument or return value as it causes IRGen crashes
|
||||
@_cdecl("swift_retain_n")
|
||||
@c
|
||||
public func swift_retain_n(object: Builtin.RawPointer, n: UInt32) -> Builtin.RawPointer {
|
||||
if !isValidPointerForNativeRetain(object: object) { return object }
|
||||
|
||||
@@ -359,20 +359,20 @@ func swift_retain_n_(object: UnsafeMutablePointer<HeapObject>, n: UInt32) -> Uns
|
||||
return unsafe object
|
||||
}
|
||||
|
||||
@_cdecl("swift_bridgeObjectRetain")
|
||||
@c
|
||||
@discardableResult
|
||||
public func swift_bridgeObjectRetain(object: Builtin.RawPointer) -> Builtin.RawPointer {
|
||||
return swift_bridgeObjectRetain_n(object: object, n: 1)
|
||||
}
|
||||
|
||||
@_cdecl("swift_bridgeObjectRetain_n")
|
||||
@c
|
||||
public func swift_bridgeObjectRetain_n(object: Builtin.RawPointer, n: UInt32) -> Builtin.RawPointer {
|
||||
let objectBits = UInt(Builtin.ptrtoint_Word(object))
|
||||
let untaggedObject = unsafe Builtin.inttoptr_Word((objectBits & HeapObject.bridgeObjectToPlainObjectMask)._builtinWordValue)
|
||||
return swift_retain_n(object: untaggedObject, n: n)
|
||||
}
|
||||
|
||||
@_cdecl("swift_release")
|
||||
@c
|
||||
public func swift_release(object: Builtin.RawPointer) {
|
||||
if !isValidPointerForNativeRetain(object: object) { return }
|
||||
|
||||
@@ -380,7 +380,7 @@ public func swift_release(object: Builtin.RawPointer) {
|
||||
unsafe swift_release_n_(object: o, n: 1)
|
||||
}
|
||||
|
||||
@_cdecl("swift_release_n")
|
||||
@c
|
||||
public func swift_release_n(object: Builtin.RawPointer, n: UInt32) {
|
||||
if !isValidPointerForNativeRetain(object: object) { return }
|
||||
|
||||
@@ -419,19 +419,19 @@ func swift_release_n_(object: UnsafeMutablePointer<HeapObject>?, n: UInt32) {
|
||||
}
|
||||
}
|
||||
|
||||
@_cdecl("swift_bridgeObjectRelease")
|
||||
@c
|
||||
public func swift_bridgeObjectRelease(object: Builtin.RawPointer) {
|
||||
swift_bridgeObjectRelease_n(object: object, n: 1)
|
||||
}
|
||||
|
||||
@_cdecl("swift_bridgeObjectRelease_n")
|
||||
@c
|
||||
public func swift_bridgeObjectRelease_n(object: Builtin.RawPointer, n: UInt32) {
|
||||
let objectBits = UInt(Builtin.ptrtoint_Word(object))
|
||||
let untaggedObject = unsafe Builtin.inttoptr_Word((objectBits & HeapObject.bridgeObjectToPlainObjectMask)._builtinWordValue)
|
||||
swift_release_n(object: untaggedObject, n: n)
|
||||
}
|
||||
|
||||
@_cdecl("swift_retainCount")
|
||||
@c
|
||||
public func swift_retainCount(object: Builtin.RawPointer) -> Int {
|
||||
if !isValidPointerForNativeRetain(object: object) { return 0 }
|
||||
let o = unsafe UnsafeMutablePointer<HeapObject>(object)
|
||||
@@ -478,12 +478,12 @@ fileprivate func storeRelaxed(_ atomic: UnsafeMutablePointer<Int>, newValue: Int
|
||||
|
||||
/// Exclusivity checking
|
||||
|
||||
@_cdecl("swift_beginAccess")
|
||||
@c
|
||||
public func swift_beginAccess(pointer: UnsafeMutableRawPointer, buffer: UnsafeMutableRawPointer, flags: UInt, pc: UnsafeMutableRawPointer) {
|
||||
// TODO: Add actual exclusivity checking.
|
||||
}
|
||||
|
||||
@_cdecl("swift_endAccess")
|
||||
@c
|
||||
public func swift_endAccess(buffer: UnsafeMutableRawPointer) {
|
||||
// TODO: Add actual exclusivity checking.
|
||||
}
|
||||
@@ -492,7 +492,7 @@ public func swift_endAccess(buffer: UnsafeMutableRawPointer) {
|
||||
|
||||
// Once
|
||||
|
||||
@_cdecl("swift_once")
|
||||
@c
|
||||
public func swift_once(predicate: UnsafeMutablePointer<Int>, fn: (@convention(c) (UnsafeMutableRawPointer)->()), context: UnsafeMutableRawPointer) {
|
||||
let checkedLoadAcquire = { predicate in
|
||||
let value = unsafe loadAcquire(predicate)
|
||||
@@ -519,12 +519,12 @@ public func swift_once(predicate: UnsafeMutablePointer<Int>, fn: (@convention(c)
|
||||
|
||||
// Misc
|
||||
|
||||
@_cdecl("swift_deletedMethodError")
|
||||
@c
|
||||
public func swift_deletedMethodError() -> Never {
|
||||
Builtin.int_trap()
|
||||
}
|
||||
|
||||
@_silgen_name("swift_willThrow") // This is actually expected to be swiftcc (@_silgen_name and not @_cdecl).
|
||||
@_silgen_name("swift_willThrow") // This is actually expected to be swiftcc (@_silgen_name and not @c).
|
||||
public func swift_willThrow() throws {
|
||||
}
|
||||
|
||||
@@ -540,7 +540,7 @@ public func swift_stdlib_random(_ buf: UnsafeMutableRawPointer, _ nbytes: Int) {
|
||||
unsafe arc4random_buf(buf: buf, nbytes: nbytes)
|
||||
}
|
||||
|
||||
@_cdecl("swift_clearSensitive")
|
||||
@c
|
||||
@inline(never)
|
||||
public func swift_clearSensitive(buf: UnsafeMutableRawPointer, nbytes: Int) {
|
||||
// TODO: use memset_s if available
|
||||
@@ -552,7 +552,6 @@ public func swift_clearSensitive(buf: UnsafeMutableRawPointer, nbytes: Int) {
|
||||
}
|
||||
}
|
||||
|
||||
@usableFromInline
|
||||
@inline(never)
|
||||
func _embeddedReportFatalError(prefix: StaticString, message: StaticString) {
|
||||
print(prefix, terminator: "")
|
||||
@@ -560,7 +559,6 @@ func _embeddedReportFatalError(prefix: StaticString, message: StaticString) {
|
||||
print(message)
|
||||
}
|
||||
|
||||
@usableFromInline
|
||||
@inline(never)
|
||||
func _embeddedReportFatalErrorInFile(prefix: StaticString, message: StaticString, file: StaticString, line: UInt) {
|
||||
print(file, terminator: ":")
|
||||
@@ -570,7 +568,6 @@ func _embeddedReportFatalErrorInFile(prefix: StaticString, message: StaticString
|
||||
print(message)
|
||||
}
|
||||
|
||||
@usableFromInline
|
||||
@inline(never)
|
||||
func _embeddedReportFatalErrorInFile(prefix: StaticString, message: UnsafeBufferPointer<UInt8>, file: StaticString, line: UInt) {
|
||||
print(file, terminator: ":")
|
||||
|
||||
Reference in New Issue
Block a user