Skip to content

Commit b49e30c

Browse files
committed
IRGen: Add an option to force emission of an async context pointer on the stack for leaf funclets
`-Xfrontend -enable-async-frame-pointer-all` rdar://135746607
1 parent 5512d83 commit b49e30c

File tree

5 files changed

+57
-0
lines changed

5 files changed

+57
-0
lines changed

include/swift/AST/IRGenOptions.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,10 @@ class IRGenOptions {
480480

481481
unsigned EmitAsyncFramePushPopMetadata : 1;
482482

483+
// Whether to force emission of a frame for all async functions
484+
// (LLVM's 'frame-pointer=all').
485+
unsigned AsyncFramePointerAll : 1;
486+
483487
/// The number of threads for multi-threaded code generation.
484488
unsigned NumThreads = 0;
485489

@@ -570,6 +574,7 @@ class IRGenOptions {
570574
ColocateTypeDescriptors(true), UseRelativeProtocolWitnessTables(false),
571575
UseFragileResilientProtocolWitnesses(false),
572576
EnableHotColdSplit(false), EmitAsyncFramePushPopMetadata(false),
577+
AsyncFramePointerAll(false),
573578
CmdArgs(), SanitizeCoverage(llvm::SanitizerCoverageOptions()),
574579
TypeInfoFilter(TypeInfoDumpFilter::All),
575580
PlatformCCallingConvention(llvm::CallingConv::C), UseCASBackend(false),

include/swift/Option/FrontendOptions.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1324,6 +1324,13 @@ def disable_async_frame_push_pop_metadata :
13241324
Flag<["-"], "disable-async-frame-push-pop-metadata">,
13251325
HelpText<"Disable async frame push pop metadata">;
13261326

1327+
def enable_async_frame_pointer_all :
1328+
Flag<["-"], "enable-async-frame-pointer-all">,
1329+
HelpText<"Always emit async frame stack frames (frame-pointer=all)">;
1330+
def disable_async_frame_pointer_all:
1331+
Flag<["-"], "disable-async-frame-pointer-all">,
1332+
HelpText<"Disable always emit async frame stack frames">;
1333+
13271334
def enable_split_cold_code :
13281335
Flag<["-"], "enable-split-cold-code">,
13291336
HelpText<"Enable splitting of cold code when optimizing">;

lib/Frontend/CompilerInvocation.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3464,6 +3464,9 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
34643464
Args.hasFlag(OPT_enable_async_frame_push_pop_metadata,
34653465
OPT_disable_async_frame_push_pop_metadata,
34663466
Opts.EmitAsyncFramePushPopMetadata);
3467+
Opts.AsyncFramePointerAll = Args.hasFlag(OPT_enable_async_frame_pointer_all,
3468+
OPT_disable_async_frame_pointer_all,
3469+
Opts.AsyncFramePointerAll);
34673470
Opts.EnableLargeLoadableTypesReg2Mem =
34683471
Args.hasFlag(OPT_enable_large_loadable_types_reg2mem,
34693472
OPT_disable_large_loadable_types_reg2mem,

lib/IRGen/IRGenSIL.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2528,6 +2528,11 @@ void IRGenSILFunction::emitSILFunction() {
25282528
CurFn->addFnAttr("async_entry");
25292529
CurFn->addFnAttr(llvm::Attribute::NoInline);
25302530
}
2531+
2532+
// For debugging purposes we always want a frame that stores the async
2533+
// context.
2534+
if (IGM.getOptions().AsyncFramePointerAll)
2535+
CurFn->addFnAttr("frame-pointer", "all");
25312536
}
25322537
if (isAsyncFn) {
25332538
IGM.noteSwiftAsyncFunctionDef();
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// RUN: %target-swift-frontend -primary-file %s -emit-irgen -module-name async -disable-availability-checking -O -enable-async-frame-pointer-all | %FileCheck %s --check-prefix=ENABLED
2+
// RUN: %target-swift-frontend -primary-file %s -emit-irgen -module-name async -disable-availability-checking -O -disable-async-frame-pointer-all | %FileCheck %s --check-prefix=DISABLED
3+
4+
// x86_64 seems to choose a different default for frame pointers.
5+
// REQUIRES: CPU=arm64 || CPU=arm64e
6+
7+
@inline(never)
8+
public func plusOne() {
9+
print("+1")
10+
}
11+
12+
@inline(never)
13+
public func minusOne() {
14+
print("-1")
15+
}
16+
// ENABLED: define{{.*}} swifttailcc void @"$s5async6calleeyyYaF"(ptr swiftasync %0) [[ATTRS:#[0-9]+]]
17+
// ENABLED: define swifttailcc void @"$s5async6callerySiSbYaF"(ptr swiftasync %0, i1 %1) [[ATTRS]]
18+
19+
// ENABLED: attributes [[ATTRS]] = { {{.*}}"frame-pointer"="all"
20+
21+
// DISABLED: define{{.*}} swifttailcc void @"$s5async6calleeyyYaF"(ptr swiftasync %0) [[ATTRS:#[0-9]+]]
22+
// DISABLED: define swifttailcc void @"$s5async6callerySiSbYaF"(ptr swiftasync %0, i1 %1) [[ATTRS]]
23+
24+
// DISABLED: attributes [[ATTRS]] = { {{.*}}"frame-pointer"="non-leaf"
25+
26+
27+
28+
public func callee() async { }
29+
30+
public func caller(_ b: Bool) async -> Int{
31+
plusOne()
32+
if b {
33+
await callee()
34+
}
35+
minusOne()
36+
return 0
37+
}

0 commit comments

Comments
 (0)