Skip to content

Commit 6504c66

Browse files
Merge pull request #3253 from aschwaighofer/swift_async_extended_frame_info_incremental_20210726
[stable/20210726] Swift async extended frame info (LLVM only)
2 parents d4f22d5 + 44b578c commit 6504c66

File tree

11 files changed

+196
-15
lines changed

11 files changed

+196
-15
lines changed

llvm/include/llvm/CodeGen/CommandFlags.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ llvm::FloatABI::ABIType getFloatABIForCalls();
7474

7575
llvm::FPOpFusion::FPOpFusionMode getFuseFPOps();
7676

77+
SwiftAsyncFramePointerMode getSwiftAsyncFramePointer();
78+
7779
bool getDontPlaceZerosInBSS();
7880

7981
bool getEnableGuaranteedTailCallOpt();

llvm/include/llvm/Target/TargetOptions.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,17 @@ namespace llvm {
110110
DisableWithDiag // Disable the abort but emit a diagnostic on failure.
111111
};
112112

113+
/// Indicates when and how the Swift async frame pointer bit should be set.
114+
enum class SwiftAsyncFramePointerMode {
115+
/// Determine whether to set the bit statically or dynamically based
116+
/// on the deployment target.
117+
DeploymentBased,
118+
/// Always set the bit.
119+
Always,
120+
/// Never set the bit.
121+
Never,
122+
};
123+
113124
class TargetOptions {
114125
public:
115126
TargetOptions()
@@ -219,6 +230,11 @@ namespace llvm {
219230
/// selection fails to lower/select an instruction.
220231
GlobalISelAbortMode GlobalISelAbort = GlobalISelAbortMode::Enable;
221232

233+
/// Control when and how the Swift async frame pointer bit should
234+
/// be set.
235+
SwiftAsyncFramePointerMode SwiftAsyncFramePointer =
236+
SwiftAsyncFramePointerMode::Always;
237+
222238
/// UseInitArray - Use .init_array instead of .ctors for static
223239
/// constructors.
224240
unsigned UseInitArray : 1;

llvm/lib/CodeGen/CommandFlags.cpp

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ CGOPT(DenormalMode::DenormalModeKind, DenormalFP32Math)
6565
CGOPT(bool, EnableHonorSignDependentRoundingFPMath)
6666
CGOPT(FloatABI::ABIType, FloatABIForCalls)
6767
CGOPT(FPOpFusion::FPOpFusionMode, FuseFPOps)
68+
CGOPT(SwiftAsyncFramePointerMode, SwiftAsyncFramePointer)
6869
CGOPT(bool, DontPlaceZerosInBSS)
6970
CGOPT(bool, EnableGuaranteedTailCallOpt)
7071
CGOPT(bool, DisableTailCalls)
@@ -277,6 +278,18 @@ codegen::RegisterCodeGenFlags::RegisterCodeGenFlags() {
277278
"Only fuse FP ops when the result won't be affected.")));
278279
CGBINDOPT(FuseFPOps);
279280

281+
static cl::opt<SwiftAsyncFramePointerMode> SwiftAsyncFramePointer(
282+
"swift-async-fp",
283+
cl::desc("Determine when the Swift async frame pointer should be set"),
284+
cl::init(SwiftAsyncFramePointerMode::Always),
285+
cl::values(clEnumValN(SwiftAsyncFramePointerMode::DeploymentBased, "auto",
286+
"Determine based on deployment target"),
287+
clEnumValN(SwiftAsyncFramePointerMode::Always, "always",
288+
"Always set the bit"),
289+
clEnumValN(SwiftAsyncFramePointerMode::Never, "never",
290+
"Never set the bit")));
291+
CGBINDOPT(SwiftAsyncFramePointer);
292+
280293
static cl::opt<bool> DontPlaceZerosInBSS(
281294
"nozero-initialized-in-bss",
282295
cl::desc("Don't place zero-initialized symbols into bss section"),
@@ -533,7 +546,7 @@ codegen::InitTargetOptionsFromCodeGenFlags(const Triple &TheTriple) {
533546
Options.ThreadModel = getThreadModel();
534547
Options.EABIVersion = getEABIVersion();
535548
Options.DebuggerTuning = getDebuggerTuningOpt();
536-
549+
Options.SwiftAsyncFramePointer = getSwiftAsyncFramePointer();
537550
return Options;
538551
}
539552

llvm/lib/Target/AArch64/AArch64FrameLowering.cpp

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,11 +1180,33 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF,
11801180
// ORR is sufficient, it is assumed a Swift kernel would initialize the TBI
11811181
// bits so that is still true.
11821182
if (HasFP && AFI->hasSwiftAsyncContext()) {
1183-
// ORR x29, x29, #0x1000_0000_0000_0000
1184-
BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXri), AArch64::FP)
1185-
.addUse(AArch64::FP)
1186-
.addImm(0x1100)
1187-
.setMIFlag(MachineInstr::FrameSetup);
1183+
switch (MF.getTarget().Options.SwiftAsyncFramePointer) {
1184+
case SwiftAsyncFramePointerMode::DeploymentBased:
1185+
if (Subtarget.swiftAsyncContextIsDynamicallySet()) {
1186+
// The special symbol below is absolute and has a *value* that can be
1187+
// combined with the frame pointer to signal an extended frame.
1188+
BuildMI(MBB, MBBI, DL, TII->get(AArch64::LOADgot), AArch64::X16)
1189+
.addExternalSymbol("swift_async_extendedFramePointerFlags",
1190+
AArch64II::MO_GOT);
1191+
BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::FP)
1192+
.addUse(AArch64::FP)
1193+
.addUse(AArch64::X16)
1194+
.addImm(Subtarget.isTargetILP32() ? 32 : 0);
1195+
break;
1196+
}
1197+
LLVM_FALLTHROUGH;
1198+
1199+
case SwiftAsyncFramePointerMode::Always:
1200+
// ORR x29, x29, #0x1000_0000_0000_0000
1201+
BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXri), AArch64::FP)
1202+
.addUse(AArch64::FP)
1203+
.addImm(0x1100)
1204+
.setMIFlag(MachineInstr::FrameSetup);
1205+
break;
1206+
1207+
case SwiftAsyncFramePointerMode::Never:
1208+
break;
1209+
}
11881210
}
11891211

11901212
// All calls are tail calls in GHC calling conv, and functions have no

llvm/lib/Target/AArch64/AArch64Subtarget.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,31 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo {
598598
}
599599
}
600600

601+
/// Return whether FrameLowering should always set the "extended frame
602+
/// present" bit in FP, or set it based on a symbol in the runtime.
603+
bool swiftAsyncContextIsDynamicallySet() const {
604+
// Older OS versions (particularly system unwinders) are confused by the
605+
// Swift extended frame, so when building code that might be run on them we
606+
// must dynamically query the concurrency library to determine whether
607+
// extended frames should be flagged as present.
608+
const Triple &TT = getTargetTriple();
609+
610+
unsigned Major, Minor, Micro;
611+
TT.getOSVersion(Major, Minor, Micro);
612+
switch(TT.getOS()) {
613+
default:
614+
return false;
615+
case Triple::IOS:
616+
case Triple::TvOS:
617+
return Major < 15;
618+
case Triple::WatchOS:
619+
return Major < 8;
620+
case Triple::MacOSX:
621+
case Triple::Darwin:
622+
return Major < 12;
623+
}
624+
}
625+
601626
void mirFileLoaded(MachineFunction &MF) const override;
602627

603628
// Return the known range for the bit length of SVE data registers. A value

llvm/lib/Target/X86/X86FrameLowering.cpp

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,11 +1363,33 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF,
13631363
unsigned StackProbeSize = STI.getTargetLowering()->getStackProbeSize(MF);
13641364

13651365
if (HasFP && X86FI->hasSwiftAsyncContext()) {
1366-
BuildMI(MBB, MBBI, DL, TII.get(X86::BTS64ri8),
1367-
MachineFramePtr)
1368-
.addUse(MachineFramePtr)
1369-
.addImm(60)
1370-
.setMIFlag(MachineInstr::FrameSetup);
1366+
switch (MF.getTarget().Options.SwiftAsyncFramePointer) {
1367+
case SwiftAsyncFramePointerMode::DeploymentBased:
1368+
if (STI.swiftAsyncContextIsDynamicallySet()) {
1369+
// The special symbol below is absolute and has a *value* suitable to be
1370+
// combined with the frame pointer directly.
1371+
BuildMI(MBB, MBBI, DL, TII.get(X86::OR64rm), MachineFramePtr)
1372+
.addUse(MachineFramePtr)
1373+
.addUse(X86::RIP)
1374+
.addImm(1)
1375+
.addUse(X86::NoRegister)
1376+
.addExternalSymbol("swift_async_extendedFramePointerFlags",
1377+
X86II::MO_GOTPCREL)
1378+
.addUse(X86::NoRegister);
1379+
break;
1380+
}
1381+
LLVM_FALLTHROUGH;
1382+
1383+
case SwiftAsyncFramePointerMode::Always:
1384+
BuildMI(MBB, MBBI, DL, TII.get(X86::BTS64ri8), MachineFramePtr)
1385+
.addUse(MachineFramePtr)
1386+
.addImm(60)
1387+
.setMIFlag(MachineInstr::FrameSetup);
1388+
break;
1389+
1390+
case SwiftAsyncFramePointerMode::Never:
1391+
break;
1392+
}
13711393
}
13721394

13731395
// Re-align the stack on 64-bit if the x86-interrupt calling convention is

llvm/lib/Target/X86/X86Subtarget.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -933,6 +933,31 @@ class X86Subtarget final : public X86GenSubtargetInfo {
933933
/// Return true if the subtarget allows calls to immediate address.
934934
bool isLegalToCallImmediateAddr() const;
935935

936+
/// Return whether FrameLowering should always set the "extended frame
937+
/// present" bit in FP, or set it based on a symbol in the runtime.
938+
bool swiftAsyncContextIsDynamicallySet() const {
939+
// Older OS versions (particularly system unwinders) are confused by the
940+
// Swift extended frame, so when building code that might be run on them we
941+
// must dynamically query the concurrency library to determine whether
942+
// extended frames should be flagged as present.
943+
const Triple &TT = getTargetTriple();
944+
945+
unsigned Major, Minor, Micro;
946+
TT.getOSVersion(Major, Minor, Micro);
947+
switch(TT.getOS()) {
948+
default:
949+
return false;
950+
case Triple::IOS:
951+
case Triple::TvOS:
952+
return Major < 15;
953+
case Triple::WatchOS:
954+
return Major < 8;
955+
case Triple::MacOSX:
956+
case Triple::Darwin:
957+
return Major < 12;
958+
}
959+
}
960+
936961
/// If we are using indirect thunks, we need to expand indirectbr to avoid it
937962
/// lowering to an actual indirect jump.
938963
bool enableIndirectBrExpand() const override {

llvm/test/CodeGen/AArch64/swift-async.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
; RUN: llc -mtriple=arm64-apple-ios %s -o - | FileCheck %s --check-prefixes=CHECK-NOAUTH,CHECK
2-
; RUN: llc -mtriple=arm64-apple-ios -mcpu=apple-a13 %s -o - | FileCheck %s --check-prefixes=CHECK-NOAUTH,CHECK
3-
; RUN: llc -mtriple=arm64e-apple-ios %s -o - | FileCheck %s --check-prefixes=CHECK-AUTH,CHECK
1+
; RUN: llc -mtriple=arm64-apple-ios15 %s -o - | FileCheck %s --check-prefixes=CHECK-NOAUTH,CHECK
2+
; RUN: llc -mtriple=arm64-apple-ios15 -mcpu=apple-a13 %s -o - | FileCheck %s --check-prefixes=CHECK-NOAUTH,CHECK
3+
; RUN: llc -mtriple=arm64e-apple-ios15 %s -o - | FileCheck %s --check-prefixes=CHECK-AUTH,CHECK
44

55
; Important details in prologue:
66
; * x22 is stored just below x29
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
; RUN: llc -mtriple arm64-apple-ios15.0.0 %s -o - | FileCheck %s --check-prefix=CHECK-STATIC
2+
; RUN: llc -mtriple arm64-apple-ios15.0.0 -swift-async-fp=auto %s -o - | FileCheck %s --check-prefix=CHECK-STATIC
3+
; RUN: llc -mtriple arm64-apple-ios15.0.0 -swift-async-fp=never %s -o - | FileCheck %s --check-prefix=CHECK-NEVER
4+
; RUN: llc -mtriple arm64-apple-ios14.9.0 -swift-async-fp=always %s -o - | FileCheck %s --check-prefix=CHECK-STATIC
5+
; RUN: llc -mtriple arm64-apple-ios14.9.0 %s -o - | FileCheck %s --check-prefix=CHECK-STATIC
6+
; RUN: llc -mtriple arm64-apple-ios14.9.0 -swift-async-fp=auto %s -o - | FileCheck %s --check-prefix=CHECK-DYNAMIC
7+
; RUN: llc -mtriple arm64-apple-tvos15.0.0 %s -o - | FileCheck %s --check-prefix=CHECK-STATIC
8+
; RUN: llc -mtriple arm64-apple-tvos14.9.0 %s -o - | FileCheck %s --check-prefix=CHECK-STATIC
9+
; RUN: llc -mtriple arm64-apple-macosx12.0.0 %s -o - | FileCheck %s --check-prefix=CHECK-STATIC
10+
; RUN: llc -mtriple arm64-apple-macosx11.9.0 %s -o - | FileCheck %s --check-prefix=CHECK-STATIC
11+
; RUN: llc -mtriple arm64_32-apple-watchos8.0.0 %s -o - | FileCheck %s --check-prefix=CHECK-STATIC
12+
; RUN: llc -mtriple arm64_32-apple-watchos7.9.0 %s -o - | FileCheck %s --check-prefix=CHECK-STATIC
13+
; RUN: llc -mtriple arm64_32-apple-watchos7.9.0 -swift-async-fp=auto %s -o - | FileCheck %s --check-prefix=CHECK-DYNAMIC-32
14+
15+
; CHECK-STATIC-LABEL: foo:
16+
; CHECK-STATIC: orr x29, x29, #0x1000000000000000
17+
18+
; CHECK-NEVER-LABEL: foo:
19+
; CHECK-NEVER-NOT: orr x29, x29, #0x1000000000000000
20+
; CHECK-NEVER-NOT: _swift_async_extendedFramePointerFlags
21+
22+
; CHECK-DYNAMIC-LABEL: foo:
23+
; CHECK-DYNAMIC: adrp x16, _swift_async_extendedFramePointerFlags@GOTPAGE
24+
; CHECK-DYNAMIC: ldr x16, [x16, _swift_async_extendedFramePointerFlags@GOTPAGEOFF]
25+
; CHECK-DYNAMIC: orr x29, x29, x16
26+
27+
; CHECK-DYNAMIC-32-LABEL: foo:
28+
; CHECK-DYNAMIC-32: adrp x16, _swift_async_extendedFramePointerFlags@GOTPAGE
29+
; CHECK-DYNAMIC-32: ldr w16, [x16, _swift_async_extendedFramePointerFlags@GOTPAGEOFF]
30+
; CHECK-DYNAMIC-32: orr x29, x29, x16, lsl #32
31+
32+
define void @foo(i8* swiftasync) "frame-pointer"="all" {
33+
ret void
34+
}

llvm/test/CodeGen/X86/swift-async.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
; RUN: llc -mtriple=x86_64-apple-darwin %s -o - | FileCheck %s
1+
; RUN: llc -mtriple=x86_64-apple-macosx12.0 %s -o - | FileCheck %s
22
; RUN: llc -mtriple=i686-apple-darwin %s -o - | FileCheck %s --check-prefix=CHECK-32
33

44

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
; RUN: llc -mtriple x86_64-apple-macosx12.0.0 %s -o - | FileCheck %s --check-prefix=CHECK-STATIC
2+
; RUN: llc -mtriple x86_64-apple-macosx12.0.0 -swift-async-fp=always %s -o - | FileCheck %s --check-prefix=CHECK-STATIC
3+
; RUN: llc -mtriple x86_64-apple-macosx12.0.0 -swift-async-fp=auto %s -o - | FileCheck %s --check-prefix=CHECK-STATIC
4+
; RUN: llc -mtriple x86_64-apple-macosx11.9.0 -swift-async-fp=always %s -o - | FileCheck %s --check-prefix=CHECK-STATIC
5+
; RUN: llc -mtriple x86_64-apple-macosx11.9.0 %s -o - | FileCheck %s --check-prefix=CHECK-STATIC
6+
; RUN: llc -mtriple x86_64-apple-macosx11.9.0 -swift-async-fp=auto %s -o - | FileCheck %s --check-prefix=CHECK-DYNAMIC
7+
; RUN: llc -mtriple x86_64-apple-macosx11.9.0 -swift-async-fp=always %s -o - | FileCheck %s --check-prefix=CHECK-STATIC
8+
; RUN: llc -mtriple x86_64-apple-macosx11.9.0 -swift-async-fp=never %s -o - | FileCheck %s --check-prefix=CHECK-NEVER
9+
10+
; CHECK-STATIC-LABEL: foo:
11+
; CHECK-STATIC: btsq $60, %rbp
12+
13+
; CHECK-DYNAMIC-LABEL: foo:
14+
; CHECK-DYNAMIC: orq _swift_async_extendedFramePointerFlags@GOTPCREL(%rip), %rbp
15+
16+
; CHECK-NEVER-LABEL: foo:
17+
; CHECK-NEVER-NOT: btsq $60, %rbp
18+
; CHECK-NEVER-NOT: _swift_async_extendedFramePointerFlags
19+
20+
define void @foo(i8* swiftasync) "frame-pointer"="all" {
21+
ret void
22+
}

0 commit comments

Comments
 (0)