From 9feb51ba90768711bffbb2d9e6c5bbdee8fea771 Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Fri, 3 Sep 2021 12:52:34 +0100 Subject: [PATCH 1/3] Merge pull request #3191 from apple/eng/PR-79357449-2 SwiftAsync: use runtime-provided flag for extended frame if back-deploying --- .../Target/AArch64/AArch64FrameLowering.cpp | 22 ++++++++++++---- llvm/lib/Target/AArch64/AArch64Subtarget.h | 25 +++++++++++++++++++ llvm/lib/Target/X86/X86FrameLowering.cpp | 22 ++++++++++++---- llvm/lib/Target/X86/X86Subtarget.h | 25 +++++++++++++++++++ llvm/test/CodeGen/AArch64/swift-async.ll | 6 ++--- .../AArch64/swift-dynamic-async-frame.ll | 25 +++++++++++++++++++ llvm/test/CodeGen/X86/swift-async.ll | 2 +- .../CodeGen/X86/swift-dynamic-async-frame.ll | 12 +++++++++ llvm/test/lit.cfg.py | 2 ++ llvm/test/lit.site.cfg.py.in | 1 + llvm/test/tools/lto/hide-linkonce-odr.ll | 2 +- llvm/test/tools/lto/no-bitcode.s | 2 +- llvm/test/tools/lto/opt-level.ll | 4 +-- llvm/test/tools/lto/print-stats.ll | 4 +-- 14 files changed, 134 insertions(+), 20 deletions(-) create mode 100644 llvm/test/CodeGen/AArch64/swift-dynamic-async-frame.ll create mode 100644 llvm/test/CodeGen/X86/swift-dynamic-async-frame.ll diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp index 51b88492e4199..9f91c7250a648 100644 --- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -1110,11 +1110,23 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF, // ORR is sufficient, it is assumed a Swift kernel would initialize the TBI // bits so that is still true. if (HasFP && AFI->hasSwiftAsyncContext()) { - // ORR x29, x29, #0x1000_0000_0000_0000 - BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXri), AArch64::FP) - .addUse(AArch64::FP) - .addImm(0x1100) - .setMIFlag(MachineInstr::FrameSetup); + if (Subtarget.swiftAsyncContextIsDynamicallySet()) { + // The special symbol below is absolute and has a *value* that can be + // combined with the frame pointer to signal an extended frame. + BuildMI(MBB, MBBI, DL, TII->get(AArch64::LOADgot), AArch64::X16) + .addExternalSymbol("swift_async_extendedFramePointerFlags", + AArch64II::MO_GOT); + BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::FP) + .addUse(AArch64::FP) + .addUse(AArch64::X16) + .addImm(Subtarget.isTargetILP32() ? 32 : 0); + } else { + // ORR x29, x29, #0x1000_0000_0000_0000 + BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXri), AArch64::FP) + .addUse(AArch64::FP) + .addImm(0x1100) + .setMIFlag(MachineInstr::FrameSetup); + } } // All calls are tail calls in GHC calling conv, and functions have no diff --git a/llvm/lib/Target/AArch64/AArch64Subtarget.h b/llvm/lib/Target/AArch64/AArch64Subtarget.h index ab44d0767dec8..2fe572b036510 100644 --- a/llvm/lib/Target/AArch64/AArch64Subtarget.h +++ b/llvm/lib/Target/AArch64/AArch64Subtarget.h @@ -566,6 +566,31 @@ class AArch64Subtarget final : public AArch64GenSubtargetInfo { } } + /// Return whether FrameLowering should always set the "extended frame + /// present" bit in FP, or set it based on a symbol in the runtime. + bool swiftAsyncContextIsDynamicallySet() const { + // Older OS versions (particularly system unwinders) are confused by the + // Swift extended frame, so when building code that might be run on them we + // must dynamically query the concurrency library to determine whether + // extended frames should be flagged as present. + const Triple &TT = getTargetTriple(); + + unsigned Major, Minor, Micro; + TT.getOSVersion(Major, Minor, Micro); + switch(TT.getOS()) { + default: + return false; + case Triple::IOS: + case Triple::TvOS: + return Major < 15; + case Triple::WatchOS: + return Major < 8; + case Triple::MacOSX: + case Triple::Darwin: + return Major < 12; + } + } + void mirFileLoaded(MachineFunction &MF) const override; // Return the known range for the bit length of SVE data registers. A value diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp index d5e2454d936b8..1b9555233fcac 100644 --- a/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/llvm/lib/Target/X86/X86FrameLowering.cpp @@ -1342,11 +1342,23 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, unsigned StackProbeSize = STI.getTargetLowering()->getStackProbeSize(MF); if (HasFP && X86FI->hasSwiftAsyncContext()) { - BuildMI(MBB, MBBI, DL, TII.get(X86::BTS64ri8), - MachineFramePtr) - .addUse(MachineFramePtr) - .addImm(60) - .setMIFlag(MachineInstr::FrameSetup); + if (STI.swiftAsyncContextIsDynamicallySet()) { + // The special symbol below is absolute and has a *value* suitable to be + // combined with the frame pointer directly. + BuildMI(MBB, MBBI, DL, TII.get(X86::OR64rm), MachineFramePtr) + .addUse(MachineFramePtr) + .addUse(X86::RIP) + .addImm(1) + .addUse(X86::NoRegister) + .addExternalSymbol("swift_async_extendedFramePointerFlags", + X86II::MO_GOTPCREL) + .addUse(X86::NoRegister); + } else { + BuildMI(MBB, MBBI, DL, TII.get(X86::BTS64ri8), MachineFramePtr) + .addUse(MachineFramePtr) + .addImm(60) + .setMIFlag(MachineInstr::FrameSetup); + } } // Re-align the stack on 64-bit if the x86-interrupt calling convention is diff --git a/llvm/lib/Target/X86/X86Subtarget.h b/llvm/lib/Target/X86/X86Subtarget.h index 9cda5b56e00b2..9cfeef095d6e6 100644 --- a/llvm/lib/Target/X86/X86Subtarget.h +++ b/llvm/lib/Target/X86/X86Subtarget.h @@ -924,6 +924,31 @@ class X86Subtarget final : public X86GenSubtargetInfo { /// Return true if the subtarget allows calls to immediate address. bool isLegalToCallImmediateAddr() const; + /// Return whether FrameLowering should always set the "extended frame + /// present" bit in FP, or set it based on a symbol in the runtime. + bool swiftAsyncContextIsDynamicallySet() const { + // Older OS versions (particularly system unwinders) are confused by the + // Swift extended frame, so when building code that might be run on them we + // must dynamically query the concurrency library to determine whether + // extended frames should be flagged as present. + const Triple &TT = getTargetTriple(); + + unsigned Major, Minor, Micro; + TT.getOSVersion(Major, Minor, Micro); + switch(TT.getOS()) { + default: + return false; + case Triple::IOS: + case Triple::TvOS: + return Major < 15; + case Triple::WatchOS: + return Major < 8; + case Triple::MacOSX: + case Triple::Darwin: + return Major < 12; + } + } + /// If we are using indirect thunks, we need to expand indirectbr to avoid it /// lowering to an actual indirect jump. bool enableIndirectBrExpand() const override { diff --git a/llvm/test/CodeGen/AArch64/swift-async.ll b/llvm/test/CodeGen/AArch64/swift-async.ll index bbf4670e76e84..dba5dacef49c2 100644 --- a/llvm/test/CodeGen/AArch64/swift-async.ll +++ b/llvm/test/CodeGen/AArch64/swift-async.ll @@ -1,6 +1,6 @@ -; RUN: llc -mtriple=arm64-apple-ios %s -o - | FileCheck %s --check-prefixes=CHECK-NOAUTH,CHECK -; RUN: llc -mtriple=arm64-apple-ios -mcpu=apple-a13 %s -o - | FileCheck %s --check-prefixes=CHECK-NOAUTH,CHECK -; RUN: llc -mtriple=arm64e-apple-ios %s -o - | FileCheck %s --check-prefixes=CHECK-AUTH,CHECK +; RUN: llc -mtriple=arm64-apple-ios15 %s -o - | FileCheck %s --check-prefixes=CHECK-NOAUTH,CHECK +; RUN: llc -mtriple=arm64-apple-ios15 -mcpu=apple-a13 %s -o - | FileCheck %s --check-prefixes=CHECK-NOAUTH,CHECK +; RUN: llc -mtriple=arm64e-apple-ios15 %s -o - | FileCheck %s --check-prefixes=CHECK-AUTH,CHECK ; Important details in prologue: ; * x22 is stored just below x29 diff --git a/llvm/test/CodeGen/AArch64/swift-dynamic-async-frame.ll b/llvm/test/CodeGen/AArch64/swift-dynamic-async-frame.ll new file mode 100644 index 0000000000000..6b17b49403f2f --- /dev/null +++ b/llvm/test/CodeGen/AArch64/swift-dynamic-async-frame.ll @@ -0,0 +1,25 @@ +; RUN: llc -mtriple arm64-apple-ios15.0.0 %s -o - | FileCheck %s --check-prefix=CHECK-STATIC +; RUN: llc -mtriple arm64-apple-ios14.9.0 %s -o - | FileCheck %s --check-prefix=CHECK-DYNAMIC +; RUN: llc -mtriple arm64-apple-tvos15.0.0 %s -o - | FileCheck %s --check-prefix=CHECK-STATIC +; RUN: llc -mtriple arm64-apple-tvos14.9.0 %s -o - | FileCheck %s --check-prefix=CHECK-DYNAMIC +; RUN: llc -mtriple arm64-apple-macosx12.0.0 %s -o - | FileCheck %s --check-prefix=CHECK-STATIC +; RUN: llc -mtriple arm64-apple-macosx11.9.0 %s -o - | FileCheck %s --check-prefix=CHECK-DYNAMIC +; RUN: llc -mtriple arm64_32-apple-watchos8.0.0 %s -o - | FileCheck %s --check-prefix=CHECK-STATIC +; RUN: llc -mtriple arm64_32-apple-watchos7.9.0 %s -o - | FileCheck %s --check-prefix=CHECK-DYNAMIC-32 + +; CHECK-STATIC-LABEL: foo: +; CHECK-STATIC: orr x29, x29, #0x1000000000000000 + +; CHECK-DYNAMIC-LABEL: foo: +; CHECK-DYNAMIC: adrp x16, _swift_async_extendedFramePointerFlags@GOTPAGE +; CHECK-DYNAMIC: ldr x16, [x16, _swift_async_extendedFramePointerFlags@GOTPAGEOFF] +; CHECK-DYNAMIC: orr x29, x29, x16 + +; CHECK-DYNAMIC-32-LABEL: foo: +; CHECK-DYNAMIC-32: adrp x16, _swift_async_extendedFramePointerFlags@GOTPAGE +; CHECK-DYNAMIC-32: ldr w16, [x16, _swift_async_extendedFramePointerFlags@GOTPAGEOFF] +; CHECK-DYNAMIC-32: orr x29, x29, x16, lsl #32 + +define void @foo(i8* swiftasync) "frame-pointer"="all" { + ret void +} diff --git a/llvm/test/CodeGen/X86/swift-async.ll b/llvm/test/CodeGen/X86/swift-async.ll index 9716fe7364896..c671917fd0d4f 100644 --- a/llvm/test/CodeGen/X86/swift-async.ll +++ b/llvm/test/CodeGen/X86/swift-async.ll @@ -1,4 +1,4 @@ -; RUN: llc -mtriple=x86_64-apple-darwin %s -o - | FileCheck %s +; RUN: llc -mtriple=x86_64-apple-macosx12.0 %s -o - | FileCheck %s ; RUN: llc -mtriple=i686-apple-darwin %s -o - | FileCheck %s --check-prefix=CHECK-32 diff --git a/llvm/test/CodeGen/X86/swift-dynamic-async-frame.ll b/llvm/test/CodeGen/X86/swift-dynamic-async-frame.ll new file mode 100644 index 0000000000000..8719aee17d53b --- /dev/null +++ b/llvm/test/CodeGen/X86/swift-dynamic-async-frame.ll @@ -0,0 +1,12 @@ +; RUN: llc -mtriple x86_64-apple-macosx12.0.0 %s -o - | FileCheck %s --check-prefix=CHECK-STATIC +; RUN: llc -mtriple x86_64-apple-macosx11.9.0 %s -o - | FileCheck %s --check-prefix=CHECK-DYNAMIC + +; CHECK-STATIC-LABEL: foo: +; CHECK-STATIC: btsq $60, %rbp + +; CHECK-DYNAMIC-LABEL: foo: +; CHECK-DYNAMIC: orq _swift_async_extendedFramePointerFlags@GOTPCREL(%rip), %rbp + +define void @foo(i8* swiftasync) "frame-pointer"="all" { + ret void +} diff --git a/llvm/test/lit.cfg.py b/llvm/test/lit.cfg.py index 9f119dd520bd4..14e4a9a005d8d 100644 --- a/llvm/test/lit.cfg.py +++ b/llvm/test/lit.cfg.py @@ -118,6 +118,8 @@ def get_asan_rtlib(): asan_rtlib = get_asan_rtlib() if asan_rtlib: ld64_cmd = 'DYLD_INSERT_LIBRARIES={} {}'.format(asan_rtlib, ld64_cmd) +if config.osx_sysroot: + ld64_cmd = '{} -syslibroot {}'.format(ld64_cmd, config.osx_sysroot) ocamlc_command = '%s ocamlc -cclib -L%s %s' % ( config.ocamlfind_executable, config.llvm_lib_dir, config.ocaml_flags) diff --git a/llvm/test/lit.site.cfg.py.in b/llvm/test/lit.site.cfg.py.in index 9765d498b50d6..c60ea943a8319 100644 --- a/llvm/test/lit.site.cfg.py.in +++ b/llvm/test/lit.site.cfg.py.in @@ -15,6 +15,7 @@ config.lit_tools_dir = path(r"@LLVM_LIT_TOOLS_DIR@") config.python_executable = "@Python3_EXECUTABLE@" config.gold_executable = "@GOLD_EXECUTABLE@" config.ld64_executable = "@LD64_EXECUTABLE@" +config.osx_sysroot = "@CMAKE_OSX_SYSROOT@" config.ocamlfind_executable = "@OCAMLFIND@" config.have_ocamlopt = @HAVE_OCAMLOPT@ config.have_ocaml_ounit = @HAVE_OCAML_OUNIT@ diff --git a/llvm/test/tools/lto/hide-linkonce-odr.ll b/llvm/test/tools/lto/hide-linkonce-odr.ll index ad7cf1b3f8baa..df4b338d2fed3 100644 --- a/llvm/test/tools/lto/hide-linkonce-odr.ll +++ b/llvm/test/tools/lto/hide-linkonce-odr.ll @@ -1,5 +1,5 @@ ; RUN: llvm-as %s -o %t.o -; RUN: %ld64 -lto_library %llvmshlibdir/libLTO.dylib -dylib -arch x86_64 -macosx_version_min 10.10.0 -o %t.dylib %t.o -save-temps -undefined dynamic_lookup -exported_symbol _c -exported_symbol _b -exported_symbol _GlobLinkonce +; RUN: %ld64 -lto_library %llvmshlibdir/libLTO.dylib -dylib -arch x86_64 -macosx_version_min 10.10.0 -o %t.dylib %t.o -save-temps -undefined dynamic_lookup -exported_symbol _c -exported_symbol _b -exported_symbol _GlobLinkonce -lSystem ; RUN: llvm-dis %t.dylib.lto.opt.bc -o - | FileCheck --check-prefix=IR %s ; check that @a is no longer a linkonce_odr definition diff --git a/llvm/test/tools/lto/no-bitcode.s b/llvm/test/tools/lto/no-bitcode.s index 8fb8e3b645851..74a8a51311bb7 100644 --- a/llvm/test/tools/lto/no-bitcode.s +++ b/llvm/test/tools/lto/no-bitcode.s @@ -2,4 +2,4 @@ ; libLTO.dylib shouldn't assert on invalid inputs. ; RUN: llvm-mc -triple=arm64-apple-ios7.0.0 -filetype=obj -o %t.o ; RUN: llvm-ar r %t.a %t.o -; RUN: %ld64 -lto_library %llvmshlibdir/libLTO.dylib -arch x86_64 -dylib -mllvm -O0 -o %t.dylib %t.a +; RUN: %ld64 -lto_library %llvmshlibdir/libLTO.dylib -arch x86_64 -dylib -mllvm -O0 -o %t.dylib %t.a -lSystem diff --git a/llvm/test/tools/lto/opt-level.ll b/llvm/test/tools/lto/opt-level.ll index b282679936a44..5113353e3b55f 100644 --- a/llvm/test/tools/lto/opt-level.ll +++ b/llvm/test/tools/lto/opt-level.ll @@ -1,7 +1,7 @@ ; RUN: llvm-as %s -o %t.o -; RUN: %ld64 -lto_library %llvmshlibdir/libLTO.dylib -arch x86_64 -dylib -mllvm -O0 -o %t.dylib %t.o +; RUN: %ld64 -lto_library %llvmshlibdir/libLTO.dylib -arch x86_64 -dylib -mllvm -O0 -o %t.dylib %t.o -lSystem ; RUN: llvm-nm --no-llvm-bc %t.dylib | FileCheck --check-prefix=CHECK-O0 %s -; RUN: %ld64 -lto_library %llvmshlibdir/libLTO.dylib -arch x86_64 -dylib -mllvm -O2 -o %t.dylib %t.o +; RUN: %ld64 -lto_library %llvmshlibdir/libLTO.dylib -arch x86_64 -dylib -mllvm -O2 -o %t.dylib %t.o -lSystem ; RUN: llvm-nm --no-llvm-bc %t.dylib | FileCheck --check-prefix=CHECK-O2 %s target triple = "x86_64-apple-macosx10.8.0" diff --git a/llvm/test/tools/lto/print-stats.ll b/llvm/test/tools/lto/print-stats.ll index 125d7d0514990..bfa47e403bfd7 100644 --- a/llvm/test/tools/lto/print-stats.ll +++ b/llvm/test/tools/lto/print-stats.ll @@ -1,6 +1,6 @@ ; RUN: llvm-as %s -o %t.o -; RUN: %ld64 -lto_library %llvmshlibdir/libLTO.dylib -arch x86_64 -dylib -mllvm -stats -o %t.dylib %t.o 2>&1 | FileCheck --check-prefix=STATS %s -; RUN: %ld64 -lto_library %llvmshlibdir/libLTO.dylib -arch x86_64 -dylib -o %t.dylib %t.o 2>&1 | FileCheck --check-prefix=NO_STATS %s +; RUN: %ld64 -lto_library %llvmshlibdir/libLTO.dylib -arch x86_64 -dylib -mllvm -stats -o %t.dylib %t.o -lSystem 2>&1 | FileCheck --check-prefix=STATS %s +; RUN: %ld64 -lto_library %llvmshlibdir/libLTO.dylib -arch x86_64 -dylib -o %t.dylib %t.o -lSystem 2>&1 | FileCheck --check-prefix=NO_STATS %s ; REQUIRES: asserts target triple = "x86_64-apple-macosx10.8.0" From daccc0e04c8e96cc416d444df42858a206806675 Mon Sep 17 00:00:00 2001 From: Doug Gregor Date: Tue, 7 Sep 2021 13:50:09 -0700 Subject: [PATCH 2/3] Add a command-line flag to control the Swift extended async frame info. Introduce a new command-line flag `-swift-async-fp={auto|always|never}` that controls how code generation sets the Swift extended async frame info bit. There are three possibilities: * `auto`: the default, which determines how to set the bit based on deployment target, either statically or dynamically via `swift_async_extendedFramePointerFlags`. * `always`: always set the bit statically, regardless of deployment target. * `never`: never set the bit, regardless of deployment target. Patch by Doug Gregor Differential Revision: https://reviews.llvm.org/D109392 --- llvm/include/llvm/CodeGen/CommandFlags.h | 2 ++ llvm/include/llvm/Target/TargetOptions.h | 16 +++++++++ llvm/lib/CodeGen/CommandFlags.cpp | 15 +++++++- .../Target/AArch64/AArch64FrameLowering.cpp | 32 +++++++++++------ llvm/lib/Target/X86/X86FrameLowering.cpp | 34 ++++++++++++------- .../AArch64/swift-dynamic-async-frame.ll | 3 ++ .../CodeGen/X86/swift-dynamic-async-frame.ll | 4 +++ 7 files changed, 82 insertions(+), 24 deletions(-) diff --git a/llvm/include/llvm/CodeGen/CommandFlags.h b/llvm/include/llvm/CodeGen/CommandFlags.h index e6c64cd4dd8e0..ef10932ef42e4 100644 --- a/llvm/include/llvm/CodeGen/CommandFlags.h +++ b/llvm/include/llvm/CodeGen/CommandFlags.h @@ -71,6 +71,8 @@ llvm::FloatABI::ABIType getFloatABIForCalls(); llvm::FPOpFusion::FPOpFusionMode getFuseFPOps(); +SwiftAsyncFramePointerMode getSwiftAsyncFramePointer(); + bool getDontPlaceZerosInBSS(); bool getEnableGuaranteedTailCallOpt(); diff --git a/llvm/include/llvm/Target/TargetOptions.h b/llvm/include/llvm/Target/TargetOptions.h index 91d372633a67d..6b0182ae5d48c 100644 --- a/llvm/include/llvm/Target/TargetOptions.h +++ b/llvm/include/llvm/Target/TargetOptions.h @@ -119,6 +119,17 @@ namespace llvm { DisableWithDiag // Disable the abort but emit a diagnostic on failure. }; + /// Indicates when and how the Swift async frame pointer bit should be set. + enum class SwiftAsyncFramePointerMode { + /// Determine whether to set the bit statically or dynamically based + /// on the deployment target. + DeploymentBased, + /// Always set the bit. + Always, + /// Never set the bit. + Never, + }; + class TargetOptions { public: TargetOptions() @@ -226,6 +237,11 @@ namespace llvm { /// selection fails to lower/select an instruction. GlobalISelAbortMode GlobalISelAbort = GlobalISelAbortMode::Enable; + /// Control when and how the Swift async frame pointer bit should + /// be set. + SwiftAsyncFramePointerMode SwiftAsyncFramePointer = + SwiftAsyncFramePointerMode::DeploymentBased; + /// UseInitArray - Use .init_array instead of .ctors for static /// constructors. unsigned UseInitArray : 1; diff --git a/llvm/lib/CodeGen/CommandFlags.cpp b/llvm/lib/CodeGen/CommandFlags.cpp index 97c110afdda42..3008d6f5cacc8 100644 --- a/llvm/lib/CodeGen/CommandFlags.cpp +++ b/llvm/lib/CodeGen/CommandFlags.cpp @@ -64,6 +64,7 @@ CGOPT(DenormalMode::DenormalModeKind, DenormalFP32Math) CGOPT(bool, EnableHonorSignDependentRoundingFPMath) CGOPT(FloatABI::ABIType, FloatABIForCalls) CGOPT(FPOpFusion::FPOpFusionMode, FuseFPOps) +CGOPT(SwiftAsyncFramePointerMode, SwiftAsyncFramePointer) CGOPT(bool, DontPlaceZerosInBSS) CGOPT(bool, EnableGuaranteedTailCallOpt) CGOPT(bool, DisableTailCalls) @@ -279,6 +280,18 @@ codegen::RegisterCodeGenFlags::RegisterCodeGenFlags() { "Only fuse FP ops when the result won't be affected."))); CGBINDOPT(FuseFPOps); + static cl::opt SwiftAsyncFramePointer( + "swift-async-fp", + cl::desc("Determine when the Swift async frame pointer should be set"), + cl::init(SwiftAsyncFramePointerMode::DeploymentBased), + cl::values(clEnumValN(SwiftAsyncFramePointerMode::DeploymentBased, "auto", + "Determine based on deployment target"), + clEnumValN(SwiftAsyncFramePointerMode::Always, "always", + "Always set the bit"), + clEnumValN(SwiftAsyncFramePointerMode::Never, "never", + "Never set the bit"))); + CGBINDOPT(SwiftAsyncFramePointer); + static cl::opt DontPlaceZerosInBSS( "nozero-initialized-in-bss", cl::desc("Don't place zero-initialized symbols into bss section"), @@ -571,7 +584,7 @@ codegen::InitTargetOptionsFromCodeGenFlags(const Triple &TheTriple) { Options.ThreadModel = getThreadModel(); Options.EABIVersion = getEABIVersion(); Options.DebuggerTuning = getDebuggerTuningOpt(); - + Options.SwiftAsyncFramePointer = getSwiftAsyncFramePointer(); return Options; } diff --git a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp index 9f91c7250a648..9e8d44bd431eb 100644 --- a/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64FrameLowering.cpp @@ -1110,22 +1110,32 @@ void AArch64FrameLowering::emitPrologue(MachineFunction &MF, // ORR is sufficient, it is assumed a Swift kernel would initialize the TBI // bits so that is still true. if (HasFP && AFI->hasSwiftAsyncContext()) { - if (Subtarget.swiftAsyncContextIsDynamicallySet()) { - // The special symbol below is absolute and has a *value* that can be - // combined with the frame pointer to signal an extended frame. - BuildMI(MBB, MBBI, DL, TII->get(AArch64::LOADgot), AArch64::X16) - .addExternalSymbol("swift_async_extendedFramePointerFlags", - AArch64II::MO_GOT); - BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::FP) - .addUse(AArch64::FP) - .addUse(AArch64::X16) - .addImm(Subtarget.isTargetILP32() ? 32 : 0); - } else { + switch (MF.getTarget().Options.SwiftAsyncFramePointer) { + case SwiftAsyncFramePointerMode::DeploymentBased: + if (Subtarget.swiftAsyncContextIsDynamicallySet()) { + // The special symbol below is absolute and has a *value* that can be + // combined with the frame pointer to signal an extended frame. + BuildMI(MBB, MBBI, DL, TII->get(AArch64::LOADgot), AArch64::X16) + .addExternalSymbol("swift_async_extendedFramePointerFlags", + AArch64II::MO_GOT); + BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXrs), AArch64::FP) + .addUse(AArch64::FP) + .addUse(AArch64::X16) + .addImm(Subtarget.isTargetILP32() ? 32 : 0); + break; + } + LLVM_FALLTHROUGH; + + case SwiftAsyncFramePointerMode::Always: // ORR x29, x29, #0x1000_0000_0000_0000 BuildMI(MBB, MBBI, DL, TII->get(AArch64::ORRXri), AArch64::FP) .addUse(AArch64::FP) .addImm(0x1100) .setMIFlag(MachineInstr::FrameSetup); + break; + + case SwiftAsyncFramePointerMode::Never: + break; } } diff --git a/llvm/lib/Target/X86/X86FrameLowering.cpp b/llvm/lib/Target/X86/X86FrameLowering.cpp index 1b9555233fcac..692b6305efe58 100644 --- a/llvm/lib/Target/X86/X86FrameLowering.cpp +++ b/llvm/lib/Target/X86/X86FrameLowering.cpp @@ -1342,22 +1342,32 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, unsigned StackProbeSize = STI.getTargetLowering()->getStackProbeSize(MF); if (HasFP && X86FI->hasSwiftAsyncContext()) { - if (STI.swiftAsyncContextIsDynamicallySet()) { - // The special symbol below is absolute and has a *value* suitable to be - // combined with the frame pointer directly. - BuildMI(MBB, MBBI, DL, TII.get(X86::OR64rm), MachineFramePtr) - .addUse(MachineFramePtr) - .addUse(X86::RIP) - .addImm(1) - .addUse(X86::NoRegister) - .addExternalSymbol("swift_async_extendedFramePointerFlags", - X86II::MO_GOTPCREL) - .addUse(X86::NoRegister); - } else { + switch (MF.getTarget().Options.SwiftAsyncFramePointer) { + case SwiftAsyncFramePointerMode::DeploymentBased: + if (STI.swiftAsyncContextIsDynamicallySet()) { + // The special symbol below is absolute and has a *value* suitable to be + // combined with the frame pointer directly. + BuildMI(MBB, MBBI, DL, TII.get(X86::OR64rm), MachineFramePtr) + .addUse(MachineFramePtr) + .addUse(X86::RIP) + .addImm(1) + .addUse(X86::NoRegister) + .addExternalSymbol("swift_async_extendedFramePointerFlags", + X86II::MO_GOTPCREL) + .addUse(X86::NoRegister); + break; + } + LLVM_FALLTHROUGH; + + case SwiftAsyncFramePointerMode::Always: BuildMI(MBB, MBBI, DL, TII.get(X86::BTS64ri8), MachineFramePtr) .addUse(MachineFramePtr) .addImm(60) .setMIFlag(MachineInstr::FrameSetup); + break; + + case SwiftAsyncFramePointerMode::Never: + break; } } diff --git a/llvm/test/CodeGen/AArch64/swift-dynamic-async-frame.ll b/llvm/test/CodeGen/AArch64/swift-dynamic-async-frame.ll index 6b17b49403f2f..667f23e966063 100644 --- a/llvm/test/CodeGen/AArch64/swift-dynamic-async-frame.ll +++ b/llvm/test/CodeGen/AArch64/swift-dynamic-async-frame.ll @@ -1,5 +1,8 @@ ; RUN: llc -mtriple arm64-apple-ios15.0.0 %s -o - | FileCheck %s --check-prefix=CHECK-STATIC +; RUN: llc -mtriple arm64-apple-ios15.0.0 -swift-async-fp=auto %s -o - | FileCheck %s --check-prefix=CHECK-STATIC +; RUN: llc -mtriple arm64-apple-ios14.9.0 -swift-async-fp=always %s -o - | FileCheck %s --check-prefix=CHECK-STATIC ; RUN: llc -mtriple arm64-apple-ios14.9.0 %s -o - | FileCheck %s --check-prefix=CHECK-DYNAMIC +; RUN: llc -mtriple arm64-apple-ios14.9.0 -swift-async-fp=auto %s -o - | FileCheck %s --check-prefix=CHECK-DYNAMIC ; RUN: llc -mtriple arm64-apple-tvos15.0.0 %s -o - | FileCheck %s --check-prefix=CHECK-STATIC ; RUN: llc -mtriple arm64-apple-tvos14.9.0 %s -o - | FileCheck %s --check-prefix=CHECK-DYNAMIC ; RUN: llc -mtriple arm64-apple-macosx12.0.0 %s -o - | FileCheck %s --check-prefix=CHECK-STATIC diff --git a/llvm/test/CodeGen/X86/swift-dynamic-async-frame.ll b/llvm/test/CodeGen/X86/swift-dynamic-async-frame.ll index 8719aee17d53b..81e49cb882e29 100644 --- a/llvm/test/CodeGen/X86/swift-dynamic-async-frame.ll +++ b/llvm/test/CodeGen/X86/swift-dynamic-async-frame.ll @@ -1,5 +1,9 @@ ; RUN: llc -mtriple x86_64-apple-macosx12.0.0 %s -o - | FileCheck %s --check-prefix=CHECK-STATIC +; RUN: llc -mtriple x86_64-apple-macosx12.0.0 -swift-async-fp=always %s -o - | FileCheck %s --check-prefix=CHECK-STATIC +; RUN: llc -mtriple x86_64-apple-macosx12.0.0 -swift-async-fp=auto %s -o - | FileCheck %s --check-prefix=CHECK-STATIC +; RUN: llc -mtriple x86_64-apple-macosx11.9.0 -swift-async-fp=always %s -o - | FileCheck %s --check-prefix=CHECK-STATIC ; RUN: llc -mtriple x86_64-apple-macosx11.9.0 %s -o - | FileCheck %s --check-prefix=CHECK-DYNAMIC +; RUN: llc -mtriple x86_64-apple-macosx11.9.0 -swift-async-fp=auto %s -o - | FileCheck %s --check-prefix=CHECK-DYNAMIC ; CHECK-STATIC-LABEL: foo: ; CHECK-STATIC: btsq $60, %rbp From bcb562525d1c4ecf17abd3d9233d4af86a16cb3f Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Wed, 8 Sep 2021 10:27:55 -0700 Subject: [PATCH 3/3] Add a new frontend flag `-fswift-async-fp={auto|always|never}` Summary: Introduce a new frontend flag `-fswift-async-fp={auto|always|never}` that controls how code generation sets the Swift extended async frame info bit. There are three possibilities: * `auto`: the default, which determines how to set the bit based on deployment target, either statically or dynamically via `swift_async_extendedFramePointerFlags`. * `always`: always set the bit statically, regardless of deployment target. * `never`: never set the bit, regardless of deployment target. Differential Revision: https://reviews.llvm.org/D109451 --- clang/include/clang/Basic/CodeGenOptions.def | 5 +++ clang/include/clang/Basic/CodeGenOptions.h | 7 ++++ clang/include/clang/Driver/Options.td | 8 ++++ clang/lib/CodeGen/BackendUtil.cpp | 15 ++++++++ clang/lib/Driver/ToolChains/Clang.cpp | 2 + clang/test/CodeGen/swift-async-extended-fp.c | 40 ++++++++++++++++++++ 6 files changed, 77 insertions(+) create mode 100644 clang/test/CodeGen/swift-async-extended-fp.c diff --git a/clang/include/clang/Basic/CodeGenOptions.def b/clang/include/clang/Basic/CodeGenOptions.def index 0528488559b3f..53f53a8f7d70f 100644 --- a/clang/include/clang/Basic/CodeGenOptions.def +++ b/clang/include/clang/Basic/CodeGenOptions.def @@ -416,6 +416,11 @@ CODEGENOPT(PassByValueIsNoAlias, 1, 0) /// according to the field declaring type width. CODEGENOPT(AAPCSBitfieldWidth, 1, 1) +// Whether to emit Swift Async function extended frame information: auto, +// never, always. +ENUM_CODEGENOPT(SwiftAsyncFramePointer, SwiftAsyncFramePointerKind, 2, + SwiftAsyncFramePointerKind::Auto) + #undef CODEGENOPT #undef ENUM_CODEGENOPT #undef VALUE_CODEGENOPT diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index bfec515067f80..e8cad42a87117 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -135,6 +135,13 @@ class CodeGenOptions : public CodeGenOptionsBase { All, // Keep all frame pointers. }; + enum class SwiftAsyncFramePointerKind { + Auto, // Choose Swift async extended frame info based on deployment target. + Always, // Unconditionally emit Swift async extended frame info. + Never, // Don't emit Swift async extended frame info. + Default = Auto, + }; + enum FiniteLoopsKind { Language, // Not specified, use language standard. Always, // All loops are assumed to be finite. diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 4d3c641ade5ad..36502dd310df2 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -1185,6 +1185,14 @@ defm pseudo_probe_for_profiling : BoolFOption<"pseudo-probe-for-profiling", def forder_file_instrumentation : Flag<["-"], "forder-file-instrumentation">, Group, Flags<[CC1Option, CoreOption]>, HelpText<"Generate instrumented code to collect order file into default.profraw file (overridden by '=' form of option or LLVM_PROFILE_FILE env var)">; +def fswift_async_fp_EQ : Joined<["-"], "fswift-async-fp=">, + Group, Flags<[CC1Option, CC1AsOption, CoreOption]>, MetaVarName<"