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
This commit is contained in:
Arnold Schwaighofer
2024-09-18 12:05:12 -07:00
parent 5512d8309e
commit b49e30c01b
5 changed files with 57 additions and 0 deletions

View File

@@ -480,6 +480,10 @@ public:
unsigned EmitAsyncFramePushPopMetadata : 1;
// Whether to force emission of a frame for all async functions
// (LLVM's 'frame-pointer=all').
unsigned AsyncFramePointerAll : 1;
/// The number of threads for multi-threaded code generation.
unsigned NumThreads = 0;
@@ -570,6 +574,7 @@ public:
ColocateTypeDescriptors(true), UseRelativeProtocolWitnessTables(false),
UseFragileResilientProtocolWitnesses(false),
EnableHotColdSplit(false), EmitAsyncFramePushPopMetadata(false),
AsyncFramePointerAll(false),
CmdArgs(), SanitizeCoverage(llvm::SanitizerCoverageOptions()),
TypeInfoFilter(TypeInfoDumpFilter::All),
PlatformCCallingConvention(llvm::CallingConv::C), UseCASBackend(false),

View File

@@ -1324,6 +1324,13 @@ def disable_async_frame_push_pop_metadata :
Flag<["-"], "disable-async-frame-push-pop-metadata">,
HelpText<"Disable async frame push pop metadata">;
def enable_async_frame_pointer_all :
Flag<["-"], "enable-async-frame-pointer-all">,
HelpText<"Always emit async frame stack frames (frame-pointer=all)">;
def disable_async_frame_pointer_all:
Flag<["-"], "disable-async-frame-pointer-all">,
HelpText<"Disable always emit async frame stack frames">;
def enable_split_cold_code :
Flag<["-"], "enable-split-cold-code">,
HelpText<"Enable splitting of cold code when optimizing">;

View File

@@ -3464,6 +3464,9 @@ static bool ParseIRGenArgs(IRGenOptions &Opts, ArgList &Args,
Args.hasFlag(OPT_enable_async_frame_push_pop_metadata,
OPT_disable_async_frame_push_pop_metadata,
Opts.EmitAsyncFramePushPopMetadata);
Opts.AsyncFramePointerAll = Args.hasFlag(OPT_enable_async_frame_pointer_all,
OPT_disable_async_frame_pointer_all,
Opts.AsyncFramePointerAll);
Opts.EnableLargeLoadableTypesReg2Mem =
Args.hasFlag(OPT_enable_large_loadable_types_reg2mem,
OPT_disable_large_loadable_types_reg2mem,

View File

@@ -2528,6 +2528,11 @@ void IRGenSILFunction::emitSILFunction() {
CurFn->addFnAttr("async_entry");
CurFn->addFnAttr(llvm::Attribute::NoInline);
}
// For debugging purposes we always want a frame that stores the async
// context.
if (IGM.getOptions().AsyncFramePointerAll)
CurFn->addFnAttr("frame-pointer", "all");
}
if (isAsyncFn) {
IGM.noteSwiftAsyncFunctionDef();

View File

@@ -0,0 +1,37 @@
// 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
// 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
// x86_64 seems to choose a different default for frame pointers.
// REQUIRES: CPU=arm64 || CPU=arm64e
@inline(never)
public func plusOne() {
print("+1")
}
@inline(never)
public func minusOne() {
print("-1")
}
// ENABLED: define{{.*}} swifttailcc void @"$s5async6calleeyyYaF"(ptr swiftasync %0) [[ATTRS:#[0-9]+]]
// ENABLED: define swifttailcc void @"$s5async6callerySiSbYaF"(ptr swiftasync %0, i1 %1) [[ATTRS]]
// ENABLED: attributes [[ATTRS]] = { {{.*}}"frame-pointer"="all"
// DISABLED: define{{.*}} swifttailcc void @"$s5async6calleeyyYaF"(ptr swiftasync %0) [[ATTRS:#[0-9]+]]
// DISABLED: define swifttailcc void @"$s5async6callerySiSbYaF"(ptr swiftasync %0, i1 %1) [[ATTRS]]
// DISABLED: attributes [[ATTRS]] = { {{.*}}"frame-pointer"="non-leaf"
public func callee() async { }
public func caller(_ b: Bool) async -> Int{
plusOne()
if b {
await callee()
}
minusOne()
return 0
}