Skip to content

Commit 9ea8671

Browse files
committed
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.
1 parent b21485d commit 9ea8671

File tree

4 files changed

+100
-58
lines changed

4 files changed

+100
-58
lines changed

lib/LLVMPasses/LLVMARCContract.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,11 @@ void SwiftARCContract::getAnalysisUsage(llvm::AnalysisUsage &AU) const {
403403
llvm::PreservedAnalyses
404404
SwiftARCContractPass::run(llvm::Function &F,
405405
llvm::FunctionAnalysisManager &AM) {
406+
// Don't touch those functions that implement reference counting in the
407+
// runtime.
408+
if (!allowArcOptimizations(F.getName()))
409+
return PreservedAnalyses::all();
410+
406411
bool changed = SwiftARCContractImpl(F).run();
407412
if (!changed)
408413
return PreservedAnalyses::all();

lib/LLVMPasses/LLVMARCOpts.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,6 +1015,12 @@ void SwiftARCOpt::getAnalysisUsage(llvm::AnalysisUsage &AU) const {
10151015

10161016
static bool runSwiftARCOpts(Function &F, SwiftRCIdentity &RC) {
10171017
bool Changed = false;
1018+
1019+
// Don't touch those functions that implement reference counting in the
1020+
// runtime.
1021+
if (!allowArcOptimizations(F.getName()))
1022+
return Changed;
1023+
10181024
ARCEntryPointBuilder B(F);
10191025

10201026
// First thing: canonicalize swift_retain and similar calls so that nothing

lib/LLVMPasses/LLVMARCOpts.h

Lines changed: 57 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,62 @@ enum RT_Kind {
2626
#include "LLVMSwift.def"
2727
};
2828

29+
inline RT_Kind classifyFunctionName(StringRef name) {
30+
return llvm::StringSwitch<RT_Kind>(name)
31+
#define SWIFT_FUNC(Name, MemBehavior, TextualName) \
32+
.Case("swift_" #TextualName, RT_ ## Name)
33+
#define SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC(Name, MemBehavior, TextualName) \
34+
.Case("__swift_" #TextualName, RT_ ## Name)
35+
#include "LLVMSwift.def"
36+
37+
// Identify "Client" versions of reference counting entry points.
38+
#define SWIFT_FUNC(Name, MemBehavior, TextualName) \
39+
.Case("swift_" #TextualName "Client", RT_ ## Name)
40+
#define SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC(Name, MemBehavior, TextualName) \
41+
.Case("__swift_" #TextualName "Client", RT_ ## Name)
42+
#include "LLVMSwift.def"
43+
44+
// Support non-atomic versions of reference counting entry points.
45+
#define SWIFT_FUNC(Name, MemBehavior, TextualName) \
46+
.Case("swift_nonatomic_" #TextualName, RT_ ## Name)
47+
#define OBJC_FUNC(Name, MemBehavior, TextualName) \
48+
.Case("objc_nonatomic_" #TextualName, RT_ ## Name)
49+
#define SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC(Name, MemBehavior, TextualName)
50+
#include "LLVMSwift.def"
51+
52+
.Default(RT_Unknown);
53+
}
54+
55+
/// Whether to allow ARC optimizations for a function with the given name.
56+
inline bool allowArcOptimizations(StringRef name) {
57+
switch (classifyFunctionName(name)) {
58+
case RT_UnknownObjectRetainN:
59+
case RT_BridgeRetainN:
60+
case RT_RetainN:
61+
case RT_UnknownObjectReleaseN:
62+
case RT_BridgeReleaseN:
63+
case RT_ReleaseN:
64+
case RT_UnknownObjectRetain:
65+
case RT_UnknownObjectRelease:
66+
case RT_Retain:
67+
case RT_ObjCRetain:
68+
case RT_ObjCRelease:
69+
case RT_RetainUnowned:
70+
case RT_Release:
71+
case RT_BridgeRetain:
72+
case RT_BridgeRelease:
73+
return false;
74+
75+
case RT_Unknown:
76+
case RT_NoMemoryAccessed:
77+
case RT_CheckUnowned:
78+
case RT_AllocObject:
79+
case RT_FixLifetime:
80+
case RT_EndBorrow:
81+
return true;
82+
}
83+
}
84+
2985
/// Take a look at the specified instruction and classify it into what kind of
3086
/// runtime entrypoint it is, if any.
3187
inline RT_Kind classifyInstruction(const llvm::Instruction &I) {
@@ -57,29 +113,7 @@ inline RT_Kind classifyInstruction(const llvm::Instruction &I) {
57113
if (F == nullptr)
58114
return RT_Unknown;
59115

60-
return llvm::StringSwitch<RT_Kind>(F->getName())
61-
#define SWIFT_FUNC(Name, MemBehavior, TextualName) \
62-
.Case("swift_" #TextualName, RT_ ## Name)
63-
#define SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC(Name, MemBehavior, TextualName) \
64-
.Case("__swift_" #TextualName, RT_ ## Name)
65-
#include "LLVMSwift.def"
66-
67-
// Identify "Client" versions of reference counting entry points.
68-
#define SWIFT_FUNC(Name, MemBehavior, TextualName) \
69-
.Case("swift_" #TextualName "Client", RT_ ## Name)
70-
#define SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC(Name, MemBehavior, TextualName) \
71-
.Case("__swift_" #TextualName "Client", RT_ ## Name)
72-
#include "LLVMSwift.def"
73-
74-
// Support non-atomic versions of reference counting entry points.
75-
#define SWIFT_FUNC(Name, MemBehavior, TextualName) \
76-
.Case("swift_nonatomic_" #TextualName, RT_ ## Name)
77-
#define OBJC_FUNC(Name, MemBehavior, TextualName) \
78-
.Case("objc_nonatomic_" #TextualName, RT_ ## Name)
79-
#define SWIFT_INTERNAL_FUNC_NEVER_NONATOMIC(Name, MemBehavior, TextualName)
80-
#include "LLVMSwift.def"
81-
82-
.Default(RT_Unknown);
116+
return classifyFunctionName(F->getName());
83117
}
84118

85119
} // end namespace swift

0 commit comments

Comments
 (0)