Skip to content

Commit 16a5d69

Browse files
committed
IRGen: Emit a weak reference to swift_async_extendedFramePointerFlags when neccessary
When we deploy to a minimum target that is not known to support extended frame information the function prolog of Swift async functions will contain a reference to swift_async_extendedFramePointerFlags. This reference needs to be weak like any async symbols. rdar://83412550
1 parent 34d16a8 commit 16a5d69

File tree

4 files changed

+61
-1
lines changed

4 files changed

+61
-1
lines changed

lib/IRGen/IRGenModule.cpp

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1644,6 +1644,7 @@ bool IRGenModule::finalize() {
16441644
if (!ClangCodeGen->GetModule())
16451645
return false;
16461646

1647+
emitSwiftAsyncExtendedFrameInfoWeakRef();
16471648
emitAutolinkInfo();
16481649
emitGlobalLists();
16491650
if (DebugInfo)
@@ -1776,3 +1777,45 @@ TypeExpansionContext IRGenModule::getMaximalTypeExpansionContext() const {
17761777
const TypeLayoutEntry &IRGenModule::getTypeLayoutEntry(SILType T) {
17771778
return Types.getTypeLayoutEntry(T);
17781779
}
1780+
1781+
/// Return whether FrameLowering should always set the "extended frame
1782+
/// present" bit in FP, or set it based on a symbol in the runtime.
1783+
static bool isSwiftAsyncContextIsDynamicallySet(llvm::Triple TT) {
1784+
// Older OS versions (particularly system unwinders) are confused by the
1785+
// Swift extended frame, so when building code that might be run on them we
1786+
// must dynamically query the concurrency library to determine whether
1787+
// extended frames should be flagged as present.
1788+
unsigned Major, Minor, Micro;
1789+
TT.getOSVersion(Major, Minor, Micro);
1790+
switch(TT.getOS()) {
1791+
default:
1792+
return false;
1793+
case llvm::Triple::IOS:
1794+
case llvm::Triple::TvOS:
1795+
return Major < 15;
1796+
case llvm::Triple::WatchOS:
1797+
return Major < 8;
1798+
case llvm::Triple::MacOSX:
1799+
case llvm::Triple::Darwin:
1800+
return Major < 12;
1801+
}
1802+
}
1803+
1804+
void IRGenModule::emitSwiftAsyncExtendedFrameInfoWeakRef() {
1805+
if (!hasSwiftAsyncFunctionDef || extendedFramePointerFlagsWeakRef)
1806+
return;
1807+
if (IRGen.Opts.SwiftAsyncFramePointer !=
1808+
SwiftAsyncFramePointerKind::Auto)
1809+
return;
1810+
if (!isSwiftAsyncContextIsDynamicallySet(Triple))
1811+
return;
1812+
1813+
// Emit a weak reference to the `swift_async_extendedFramePointerFlags` symbol
1814+
// needed by Swift async functions.
1815+
auto symbolName = "swift_async_extendedFramePointerFlags";
1816+
if ((extendedFramePointerFlagsWeakRef = Module.getGlobalVariable(symbolName)))
1817+
return;
1818+
extendedFramePointerFlagsWeakRef = new llvm::GlobalVariable(Module, Int8PtrTy, false,
1819+
llvm::GlobalValue::ExternalWeakLinkage, nullptr,
1820+
symbolName);
1821+
}

lib/IRGen/IRGenModule.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1691,7 +1691,16 @@ private: \
16911691
void addLazyConformances(const IterableDeclContext *idc);
16921692

16931693
//--- Global context emission --------------------------------------------------
1694+
bool hasSwiftAsyncFunctionDef = false;
1695+
llvm::Value *extendedFramePointerFlagsWeakRef = nullptr;
1696+
1697+
/// Emit a weak reference to the `swift_async_extendedFramePointerFlags`
1698+
/// symbol needed by Swift async functions.
1699+
void emitSwiftAsyncExtendedFrameInfoWeakRef();
16941700
public:
1701+
void noteSwiftAsyncFunctionDef() {
1702+
hasSwiftAsyncFunctionDef = true;
1703+
}
16951704
void emitRuntimeRegistration();
16961705
void emitVTableStubs();
16971706
void emitTypeVerifier();

lib/IRGen/IRGenSIL.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2181,12 +2181,16 @@ void IRGenSILFunction::emitSILFunction() {
21812181
IGM.IRGen.addDynamicReplacement(CurSILFn);
21822182

21832183
auto funcTy = CurSILFn->getLoweredFunctionType();
2184-
if (funcTy->isAsync() && funcTy->getLanguage() == SILFunctionLanguage::Swift) {
2184+
bool isAsyncFn = funcTy->isAsync();
2185+
if (isAsyncFn && funcTy->getLanguage() == SILFunctionLanguage::Swift) {
21852186
emitAsyncFunctionPointer(IGM,
21862187
CurFn,
21872188
LinkEntity::forSILFunction(CurSILFn),
21882189
getAsyncContextLayout(*this).getSize());
21892190
}
2191+
if (isAsyncFn) {
2192+
IGM.noteSwiftAsyncFunctionDef();
2193+
}
21902194

21912195
// Configure the dominance resolver.
21922196
// TODO: consider re-using a dom analysis from the PassManager

test/IRGen/swift_async_extended_frame_info.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,7 @@ public func someAsyncFunction() async {
2121
// NEVER: s31swift_async_extended_frame_info17someAsyncFunctionyyYaF:
2222
// NEVER-NOT: _swift_async_extendedFramePointerFlags
2323
// NEVER-NOT: btsq $60
24+
25+
// AUTO: .weak_reference _swift_async_extendedFramePointerFlags
26+
// NEVER-NOT: .weak_reference _swift_async_extendedFramePointerFlags
27+
// ALWAYS-NOT: .weak_reference _swift_async_extendedFramePointerFlags

0 commit comments

Comments
 (0)