From d8075e878158c472b53b19de2c81bb18f254a372 Mon Sep 17 00:00:00 2001 From: Daniel Kiss Date: Wed, 27 Oct 2021 10:32:11 +0200 Subject: [PATCH] Reland "[ARM] __cxa_end_cleanup should be called instead of _UnwindResume." This is relanding commit da1d1a08694bbfe0ea7a23ea094612436e8a2dd0 . This patch additionally addresses failures found in buildbots & post review comments. ARM EHABI[1] specifies the __cxa_end_cleanup to be called after cleanup. It will call the UnwindResume. __cxa_begin_cleanup will be called from libcxxabi while __cxa_end_cleanup is never called. This will trigger a termination when a foreign exception is processed while UnwindResume is called because the global state will be wrong due to the missing __cxa_end_cleanup call. Additional test here: D109856 [1] https://github.com/ARM-software/abi-aa/blob/main/ehabi32/ehabi32.rst#941compiler-helper-functions Reviewed By: logan Differential Revision: https://reviews.llvm.org/D111703 --- libcxxabi/src/cxa_exception.cpp | 18 ++--- llvm/include/llvm/ADT/Triple.h | 13 +++ llvm/include/llvm/IR/RuntimeLibcalls.def | 1 + llvm/lib/CodeGen/DwarfEHPrepare.cpp | 79 +++++++++++-------- llvm/lib/Target/ARM/ARMSubtarget.h | 9 +-- llvm/test/CodeGen/ARM/debug-frame.ll | 68 ++++++++-------- .../ARM/{eh-resume-darwin.ll => eh-resume.ll} | 4 + llvm/test/CodeGen/ARM/eh-resume2.ll | 32 ++++++++ llvm/test/CodeGen/ARM/ehabi.ll | 40 +++++----- 9 files changed, 158 insertions(+), 106 deletions(-) rename llvm/test/CodeGen/ARM/{eh-resume-darwin.ll => eh-resume.ll} (76%) create mode 100644 llvm/test/CodeGen/ARM/eh-resume2.ll diff --git a/libcxxabi/src/cxa_exception.cpp b/libcxxabi/src/cxa_exception.cpp index 35956f197f59..7044cb9a43f3 100644 --- a/libcxxabi/src/cxa_exception.cpp +++ b/libcxxabi/src/cxa_exception.cpp @@ -341,8 +341,10 @@ unwinding with _Unwind_Resume. According to ARM EHABI 8.4.1, __cxa_end_cleanup() should not clobber any register, thus we have to write this function in assembly so that we can save {r1, r2, r3}. We don't have to save r0 because it is the return value and the -first argument to _Unwind_Resume(). In addition, we are saving r4 in order to -align the stack to 16 bytes, even though it is a callee-save register. +first argument to _Unwind_Resume(). In addition, we are saving lr in order to +align the stack to 16 bytes and lr will be used to identify the caller and its +frame information. _Unwind_Resume never return and we need to keep the original +lr so just branch to it. */ __attribute__((used)) static _Unwind_Exception * __cxa_end_cleanup_impl() @@ -372,18 +374,16 @@ __cxa_end_cleanup_impl() return &exception_header->unwindHeader; } -asm ( - " .pushsection .text.__cxa_end_cleanup,\"ax\",%progbits\n" +asm(" .pushsection .text.__cxa_end_cleanup,\"ax\",%progbits\n" " .globl __cxa_end_cleanup\n" " .type __cxa_end_cleanup,%function\n" "__cxa_end_cleanup:\n" - " push {r1, r2, r3, r4}\n" + " push {r1, r2, r3, lr}\n" " bl __cxa_end_cleanup_impl\n" " pop {r1, r2, r3, r4}\n" - " bl _Unwind_Resume\n" - " bl abort\n" - " .popsection" -); + " mov lr, r4\n" + " b _Unwind_Resume\n" + " .popsection"); #endif // defined(_LIBCXXABI_ARM_EHABI) /* diff --git a/llvm/include/llvm/ADT/Triple.h b/llvm/include/llvm/ADT/Triple.h index e18fbf5c8457..c848314cd9e9 100644 --- a/llvm/include/llvm/ADT/Triple.h +++ b/llvm/include/llvm/ADT/Triple.h @@ -721,6 +721,19 @@ public: return getArch() == Triple::arm || getArch() == Triple::armeb; } + /// Tests whether the target supports the EHABI exception + /// handling standard. + bool isTargetEHABICompatible() const { + return (isARM() || isThumb()) && + (getEnvironment() == Triple::EABI || + getEnvironment() == Triple::GNUEABI || + getEnvironment() == Triple::MuslEABI || + getEnvironment() == Triple::EABIHF || + getEnvironment() == Triple::GNUEABIHF || + getEnvironment() == Triple::MuslEABIHF || isAndroid()) && + isOSBinFormatELF(); + } + /// Tests whether the target is AArch64 (little and big endian). bool isAArch64() const { return getArch() == Triple::aarch64 || getArch() == Triple::aarch64_be || diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.def b/llvm/include/llvm/IR/RuntimeLibcalls.def index dd28780ac946..5f295660557a 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.def +++ b/llvm/include/llvm/IR/RuntimeLibcalls.def @@ -432,6 +432,7 @@ HANDLE_LIBCALL(MEMSET_ELEMENT_UNORDERED_ATOMIC_16, "__llvm_memset_element_unorde // Exception handling HANDLE_LIBCALL(UNWIND_RESUME, "_Unwind_Resume") +HANDLE_LIBCALL(CXA_END_CLEANUP, "__cxa_end_cleanup") // Note: there are two sets of atomics libcalls; see // for more info on the diff --git a/llvm/lib/CodeGen/DwarfEHPrepare.cpp b/llvm/lib/CodeGen/DwarfEHPrepare.cpp index fde7b942665d..fb8a3e383950 100644 --- a/llvm/lib/CodeGen/DwarfEHPrepare.cpp +++ b/llvm/lib/CodeGen/DwarfEHPrepare.cpp @@ -14,6 +14,7 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" +#include "llvm/ADT/Triple.h" #include "llvm/Analysis/CFG.h" #include "llvm/Analysis/DomTreeUpdater.h" #include "llvm/Analysis/EHPersonalities.h" @@ -54,13 +55,11 @@ namespace { class DwarfEHPrepare { CodeGenOpt::Level OptLevel; - // RewindFunction - _Unwind_Resume or the target equivalent. - FunctionCallee &RewindFunction; - Function &F; const TargetLowering &TLI; DomTreeUpdater *DTU; const TargetTransformInfo *TTI; + const Triple &TargetTriple; /// Return the exception object from the value passed into /// the 'resume' instruction (typically an aggregate). Clean up any dead @@ -78,11 +77,11 @@ class DwarfEHPrepare { bool InsertUnwindResumeCalls(); public: - DwarfEHPrepare(CodeGenOpt::Level OptLevel_, FunctionCallee &RewindFunction_, - Function &F_, const TargetLowering &TLI_, DomTreeUpdater *DTU_, - const TargetTransformInfo *TTI_) - : OptLevel(OptLevel_), RewindFunction(RewindFunction_), F(F_), TLI(TLI_), - DTU(DTU_), TTI(TTI_) {} + DwarfEHPrepare(CodeGenOpt::Level OptLevel_, Function &F_, + const TargetLowering &TLI_, DomTreeUpdater *DTU_, + const TargetTransformInfo *TTI_, const Triple &TargetTriple_) + : OptLevel(OptLevel_), F(F_), TLI(TLI_), DTU(DTU_), TTI(TTI_), + TargetTriple(TargetTriple_) {} bool run(); }; @@ -211,13 +210,28 @@ bool DwarfEHPrepare::InsertUnwindResumeCalls() { if (ResumesLeft == 0) return true; // We pruned them all. - // Find the rewind function if we didn't already. - if (!RewindFunction) { - FunctionType *FTy = + // RewindFunction - _Unwind_Resume or the target equivalent. + FunctionCallee RewindFunction; + CallingConv::ID RewindFunctionCallingConv; + FunctionType *FTy; + const char *RewindName; + bool DoesRewindFunctionNeedExceptionObject; + + if ((Pers == EHPersonality::GNU_CXX || Pers == EHPersonality::GNU_CXX_SjLj) && + TargetTriple.isTargetEHABICompatible()) { + RewindName = TLI.getLibcallName(RTLIB::CXA_END_CLEANUP); + FTy = FunctionType::get(Type::getVoidTy(Ctx), false); + RewindFunctionCallingConv = + TLI.getLibcallCallingConv(RTLIB::CXA_END_CLEANUP); + DoesRewindFunctionNeedExceptionObject = false; + } else { + RewindName = TLI.getLibcallName(RTLIB::UNWIND_RESUME); + FTy = FunctionType::get(Type::getVoidTy(Ctx), Type::getInt8PtrTy(Ctx), false); - const char *RewindName = TLI.getLibcallName(RTLIB::UNWIND_RESUME); - RewindFunction = F.getParent()->getOrInsertFunction(RewindName, FTy); + RewindFunctionCallingConv = TLI.getLibcallCallingConv(RTLIB::UNWIND_RESUME); + DoesRewindFunctionNeedExceptionObject = true; } + RewindFunction = F.getParent()->getOrInsertFunction(RewindName, FTy); // Create the basic block where the _Unwind_Resume call will live. if (ResumesLeft == 1) { @@ -226,10 +240,14 @@ bool DwarfEHPrepare::InsertUnwindResumeCalls() { ResumeInst *RI = Resumes.front(); BasicBlock *UnwindBB = RI->getParent(); Value *ExnObj = GetExceptionObject(RI); + llvm::SmallVector RewindFunctionArgs; + if (DoesRewindFunctionNeedExceptionObject) + RewindFunctionArgs.push_back(ExnObj); - // Call the _Unwind_Resume function. - CallInst *CI = CallInst::Create(RewindFunction, ExnObj, "", UnwindBB); - CI->setCallingConv(TLI.getLibcallCallingConv(RTLIB::UNWIND_RESUME)); + // Call the rewind function. + CallInst *CI = + CallInst::Create(RewindFunction, RewindFunctionArgs, "", UnwindBB); + CI->setCallingConv(RewindFunctionCallingConv); // We never expect _Unwind_Resume to return. CI->setDoesNotReturn(); @@ -240,6 +258,8 @@ bool DwarfEHPrepare::InsertUnwindResumeCalls() { std::vector Updates; Updates.reserve(Resumes.size()); + llvm::SmallVector RewindFunctionArgs; + BasicBlock *UnwindBB = BasicBlock::Create(Ctx, "unwind_resume", &F); PHINode *PN = PHINode::Create(Type::getInt8PtrTy(Ctx), ResumesLeft, "exn.obj", UnwindBB); @@ -257,9 +277,13 @@ bool DwarfEHPrepare::InsertUnwindResumeCalls() { ++NumResumesLowered; } + if (DoesRewindFunctionNeedExceptionObject) + RewindFunctionArgs.push_back(PN); + // Call the function. - CallInst *CI = CallInst::Create(RewindFunction, PN, "", UnwindBB); - CI->setCallingConv(TLI.getLibcallCallingConv(RTLIB::UNWIND_RESUME)); + CallInst *CI = + CallInst::Create(RewindFunction, RewindFunctionArgs, "", UnwindBB); + CI->setCallingConv(RewindFunctionCallingConv); // We never expect _Unwind_Resume to return. CI->setDoesNotReturn(); @@ -277,22 +301,20 @@ bool DwarfEHPrepare::run() { return Changed; } -static bool prepareDwarfEH(CodeGenOpt::Level OptLevel, - FunctionCallee &RewindFunction, Function &F, +static bool prepareDwarfEH(CodeGenOpt::Level OptLevel, Function &F, const TargetLowering &TLI, DominatorTree *DT, - const TargetTransformInfo *TTI) { + const TargetTransformInfo *TTI, + const Triple &TargetTriple) { DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy); - return DwarfEHPrepare(OptLevel, RewindFunction, F, TLI, DT ? &DTU : nullptr, - TTI) + return DwarfEHPrepare(OptLevel, F, TLI, DT ? &DTU : nullptr, TTI, + TargetTriple) .run(); } namespace { class DwarfEHPrepareLegacyPass : public FunctionPass { - // RewindFunction - _Unwind_Resume or the target equivalent. - FunctionCallee RewindFunction = nullptr; CodeGenOpt::Level OptLevel; @@ -315,12 +337,7 @@ public: DT = &getAnalysis().getDomTree(); TTI = &getAnalysis().getTTI(F); } - return prepareDwarfEH(OptLevel, RewindFunction, F, TLI, DT, TTI); - } - - bool doFinalization(Module &M) override { - RewindFunction = nullptr; - return false; + return prepareDwarfEH(OptLevel, F, TLI, DT, TTI, TM.getTargetTriple()); } void getAnalysisUsage(AnalysisUsage &AU) const override { diff --git a/llvm/lib/Target/ARM/ARMSubtarget.h b/llvm/lib/Target/ARM/ARMSubtarget.h index 807bbc11bd94..68390c990268 100644 --- a/llvm/lib/Target/ARM/ARMSubtarget.h +++ b/llvm/lib/Target/ARM/ARMSubtarget.h @@ -792,14 +792,7 @@ public: // ARM Targets that support EHABI exception handling standard // Darwin uses SjLj. Other targets might need more checks. bool isTargetEHABICompatible() const { - return (TargetTriple.getEnvironment() == Triple::EABI || - TargetTriple.getEnvironment() == Triple::GNUEABI || - TargetTriple.getEnvironment() == Triple::MuslEABI || - TargetTriple.getEnvironment() == Triple::EABIHF || - TargetTriple.getEnvironment() == Triple::GNUEABIHF || - TargetTriple.getEnvironment() == Triple::MuslEABIHF || - isTargetAndroid()) && - !isTargetDarwin() && !isTargetWindows(); + return TargetTriple.isTargetEHABICompatible(); } bool isTargetHardFloat() const; diff --git a/llvm/test/CodeGen/ARM/debug-frame.ll b/llvm/test/CodeGen/ARM/debug-frame.ll index b561be465d25..b7660443a7d3 100644 --- a/llvm/test/CodeGen/ARM/debug-frame.ll +++ b/llvm/test/CodeGen/ARM/debug-frame.ll @@ -197,29 +197,27 @@ declare void @_ZSt9terminatev() ; CHECK-V7-FP-LABEL: _Z4testiiiiiddddd: ; CHECK-V7-FP: .cfi_startproc -; CHECK-V7-FP: push {r4, r10, r11, lr} -; CHECK-V7-FP: .cfi_def_cfa_offset 16 +; CHECK-V7-FP: push {r11, lr} +; CHECK-V7-FP: .cfi_def_cfa_offset 8 ; CHECK-V7-FP: .cfi_offset lr, -4 ; CHECK-V7-FP: .cfi_offset r11, -8 -; CHECK-V7-FP: .cfi_offset r10, -12 -; CHECK-V7-FP: .cfi_offset r4, -16 -; CHECK-V7-FP: add r11, sp, #8 -; CHECK-V7-FP: .cfi_def_cfa r11, 8 +; CHECK-V7-FP: mov r11, sp +; CHECK-V7-FP: .cfi_def_cfa_register r11 ; CHECK-V7-FP: vpush {d8, d9, d10, d11, d12} -; CHECK-V7-FP: .cfi_offset d12, -24 -; CHECK-V7-FP: .cfi_offset d11, -32 -; CHECK-V7-FP: .cfi_offset d10, -40 -; CHECK-V7-FP: .cfi_offset d9, -48 -; CHECK-V7-FP: .cfi_offset d8, -56 +; CHECK-V7-FP: .cfi_offset d12, -16 +; CHECK-V7-FP: .cfi_offset d11, -24 +; CHECK-V7-FP: .cfi_offset d10, -32 +; CHECK-V7-FP: .cfi_offset d9, -40 +; CHECK-V7-FP: .cfi_offset d8, -48 ; CHECK-V7-FP: sub sp, sp, #24 ; CHECK-V7-FP: .cfi_endproc ; CHECK-V7-FP-ELIM-LABEL: _Z4testiiiiiddddd: ; CHECK-V7-FP-ELIM: .cfi_startproc -; CHECK-V7-FP-ELIM: push {r4, lr} +; CHECK-V7-FP-ELIM: push {r11, lr} ; CHECK-V7-FP-ELIM: .cfi_def_cfa_offset 8 ; CHECK-V7-FP-ELIM: .cfi_offset lr, -4 -; CHECK-V7-FP-ELIM: .cfi_offset r4, -8 +; CHECK-V7-FP-ELIM: .cfi_offset r11, -8 ; CHECK-V7-FP-ELIM: vpush {d8, d9, d10, d11, d12} ; CHECK-V7-FP-ELIM: .cfi_def_cfa_offset 48 ; CHECK-V7-FP-ELIM: .cfi_offset d12, -16 @@ -260,29 +258,27 @@ declare void @_ZSt9terminatev() ; CHECK-THUMB-V7-FP-LABEL: _Z4testiiiiiddddd: ; CHECK-THUMB-V7-FP: .cfi_startproc -; CHECK-THUMB-V7-FP: push {r4, r6, r7, lr} -; CHECK-THUMB-V7-FP: .cfi_def_cfa_offset 16 +; CHECK-THUMB-V7-FP: push {r7, lr} +; CHECK-THUMB-V7-FP: .cfi_def_cfa_offset 8 ; CHECK-THUMB-V7-FP: .cfi_offset lr, -4 ; CHECK-THUMB-V7-FP: .cfi_offset r7, -8 -; CHECK-THUMB-V7-FP: .cfi_offset r6, -12 -; CHECK-THUMB-V7-FP: .cfi_offset r4, -16 -; CHECK-THUMB-V7-FP: add r7, sp, #8 -; CHECK-THUMB-V7-FP: .cfi_def_cfa r7, 8 +; CHECK-THUMB-V7-FP: mov r7, sp +; CHECK-THUMB-V7-FP: .cfi_def_cfa_register r7 ; CHECK-THUMB-V7-FP: vpush {d8, d9, d10, d11, d12} -; CHECK-THUMB-V7-FP: .cfi_offset d12, -24 -; CHECK-THUMB-V7-FP: .cfi_offset d11, -32 -; CHECK-THUMB-V7-FP: .cfi_offset d10, -40 -; CHECK-THUMB-V7-FP: .cfi_offset d9, -48 -; CHECK-THUMB-V7-FP: .cfi_offset d8, -56 +; CHECK-THUMB-V7-FP: .cfi_offset d12, -16 +; CHECK-THUMB-V7-FP: .cfi_offset d11, -24 +; CHECK-THUMB-V7-FP: .cfi_offset d10, -32 +; CHECK-THUMB-V7-FP: .cfi_offset d9, -40 +; CHECK-THUMB-V7-FP: .cfi_offset d8, -48 ; CHECK-THUMB-V7-FP: sub sp, #24 ; CHECK-THUMB-V7-FP: .cfi_endproc ; CHECK-THUMB-V7-FP-ELIM-LABEL: _Z4testiiiiiddddd: ; CHECK-THUMB-V7-FP-ELIM: .cfi_startproc -; CHECK-THUMB-V7-FP-ELIM: push {r4, lr} +; CHECK-THUMB-V7-FP-ELIM: push {r7, lr} ; CHECK-THUMB-V7-FP-ELIM: .cfi_def_cfa_offset 8 ; CHECK-THUMB-V7-FP-ELIM: .cfi_offset lr, -4 -; CHECK-THUMB-V7-FP-ELIM: .cfi_offset r4, -8 +; CHECK-THUMB-V7-FP-ELIM: .cfi_offset r7, -8 ; CHECK-THUMB-V7-FP-ELIM: vpush {d8, d9, d10, d11, d12} ; CHECK-THUMB-V7-FP-ELIM: .cfi_def_cfa_offset 48 ; CHECK-THUMB-V7-FP-ELIM: .cfi_offset d12, -16 @@ -296,20 +292,18 @@ declare void @_ZSt9terminatev() ; CHECK-THUMB-V7-FP-NOIAS-LABEL: _Z4testiiiiiddddd: ; CHECK-THUMB-V7-FP-NOIAS: .cfi_startproc -; CHECK-THUMB-V7-FP-NOIAS: push {r4, r6, r7, lr} -; CHECK-THUMB-V7-FP-NOIAS: .cfi_def_cfa_offset 16 +; CHECK-THUMB-V7-FP-NOIAS: push {r7, lr} +; CHECK-THUMB-V7-FP-NOIAS: .cfi_def_cfa_offset 8 ; CHECK-THUMB-V7-FP-NOIAS: .cfi_offset 14, -4 ; CHECK-THUMB-V7-FP-NOIAS: .cfi_offset 7, -8 -; CHECK-THUMB-V7-FP-NOIAS: .cfi_offset 6, -12 -; CHECK-THUMB-V7-FP-NOIAS: .cfi_offset 4, -16 -; CHECK-THUMB-V7-FP-NOIAS: add r7, sp, #8 -; CHECK-THUMB-V7-FP-NOIAS: .cfi_def_cfa 7, 8 +; CHECK-THUMB-V7-FP-NOIAS: mov r7, sp +; CHECK-THUMB-V7-FP-NOIAS: .cfi_def_cfa_register 7 ; CHECK-THUMB-V7-FP-NOIAS: vpush {d8, d9, d10, d11, d12} -; CHECK-THUMB-V7-FP-NOIAS: .cfi_offset 268, -24 -; CHECK-THUMB-V7-FP-NOIAS: .cfi_offset 267, -32 -; CHECK-THUMB-V7-FP-NOIAS: .cfi_offset 266, -40 -; CHECK-THUMB-V7-FP-NOIAS: .cfi_offset 265, -48 -; CHECK-THUMB-V7-FP-NOIAS: .cfi_offset 264, -56 +; CHECK-THUMB-V7-FP-NOIAS: .cfi_offset 268, -16 +; CHECK-THUMB-V7-FP-NOIAS: .cfi_offset 267, -24 +; CHECK-THUMB-V7-FP-NOIAS: .cfi_offset 266, -32 +; CHECK-THUMB-V7-FP-NOIAS: .cfi_offset 265, -40 +; CHECK-THUMB-V7-FP-NOIAS: .cfi_offset 264, -48 ; CHECK-THUMB-V7-FP-NOIAS: sub sp, #24 ; CHECK-THUMB-V7-FP-NOIAS: .cfi_endproc diff --git a/llvm/test/CodeGen/ARM/eh-resume-darwin.ll b/llvm/test/CodeGen/ARM/eh-resume.ll similarity index 76% rename from llvm/test/CodeGen/ARM/eh-resume-darwin.ll rename to llvm/test/CodeGen/ARM/eh-resume.ll index 6c2716bffa6d..12fe2667b8f0 100644 --- a/llvm/test/CodeGen/ARM/eh-resume-darwin.ll +++ b/llvm/test/CodeGen/ARM/eh-resume.ll @@ -2,6 +2,8 @@ ; RUN: llc < %s -mtriple=armv7-apple-watchos -arm-atomic-cfg-tidy=0 | FileCheck %s -check-prefix=IOS ; RUN: llc < %s -mtriple=armv7k-apple-ios -arm-atomic-cfg-tidy=0 | FileCheck %s -check-prefix=WATCHABI ; RUN: llc < %s -mtriple=armv7k-apple-watchos -arm-atomic-cfg-tidy=0 | FileCheck %s -check-prefix=WATCHABI +; RUN: llc < %s -mtriple=armv7-none-gnueabihf -arm-atomic-cfg-tidy=0 | FileCheck %s -check-prefix=EABI +; RUN: llc < %s -mtriple=armv7-none-none -arm-atomic-cfg-tidy=0 | FileCheck %s -check-prefix=ABI declare void @func() @@ -23,3 +25,5 @@ lpad: ; IOS: __Unwind_SjLj_Resume ; WATCHABI: __Unwind_Resume +; EABI: __cxa_end_cleanup +; ABI: _Unwind_Resume diff --git a/llvm/test/CodeGen/ARM/eh-resume2.ll b/llvm/test/CodeGen/ARM/eh-resume2.ll new file mode 100644 index 000000000000..d30b507255c4 --- /dev/null +++ b/llvm/test/CodeGen/ARM/eh-resume2.ll @@ -0,0 +1,32 @@ +; RUN: llc < %s -mtriple=armv7-apple-ios -arm-atomic-cfg-tidy=0 | FileCheck %s -check-prefix=IOS +; RUN: llc < %s -mtriple=armv7-apple-watchos -arm-atomic-cfg-tidy=0 | FileCheck %s -check-prefix=IOS +; RUN: llc < %s -mtriple=armv7k-apple-ios -arm-atomic-cfg-tidy=0 | FileCheck %s -check-prefix=WATCHABI +; RUN: llc < %s -mtriple=armv7k-apple-watchos -arm-atomic-cfg-tidy=0 | FileCheck %s -check-prefix=WATCHABI +; RUN: llc < %s -mtriple=armv7-none-gnueabihf -arm-atomic-cfg-tidy=0 | FileCheck %s -check-prefix=EABI +; RUN: llc < %s -mtriple=armv7-none-none -arm-atomic-cfg-tidy=0 | FileCheck %s -check-prefix=ABI + +; ARM EABI for C++/__gxx_personality* specifies __cxa_end_cleanup, but for C code / __gcc_personality* +; the _Unwind_Resume is required. + +declare void @func() + +declare i32 @__gcc_personality_v0(...) + +define void @test0() personality i8* bitcast (i32 (...)* @__gcc_personality_v0 to i8*) { +entry: + invoke void @func() + to label %cont unwind label %lpad + +cont: + ret void + +lpad: + %exn = landingpad { i8*, i32 } + cleanup + resume { i8*, i32 } %exn +} + +; IOS: __Unwind_SjLj_Resume +; WATCHABI: __Unwind_Resume +; EABI: _Unwind_Resume +; ABI: _Unwind_Resume diff --git a/llvm/test/CodeGen/ARM/ehabi.ll b/llvm/test/CodeGen/ARM/ehabi.ll index 5c4a2b620a1f..c8c0b5b61980 100644 --- a/llvm/test/CodeGen/ARM/ehabi.ll +++ b/llvm/test/CodeGen/ARM/ehabi.ll @@ -181,10 +181,10 @@ declare void @_ZSt9terminatev() ; CHECK-V7-FP-LABEL: _Z4testiiiiiddddd: ; CHECK-V7-FP: .fnstart -; CHECK-V7-FP: .save {r4, r10, r11, lr} -; CHECK-V7-FP: push {r4, r10, r11, lr} -; CHECK-V7-FP: .setfp r11, sp, #8 -; CHECK-V7-FP: add r11, sp, #8 +; CHECK-V7-FP: .save {r11, lr} +; CHECK-V7-FP: push {r11, lr} +; CHECK-V7-FP: .setfp r11, sp +; CHECK-V7-FP: mov r11, sp ; CHECK-V7-FP: .vsave {d8, d9, d10, d11, d12} ; CHECK-V7-FP: vpush {d8, d9, d10, d11, d12} ; CHECK-V7-FP: .pad #24 @@ -195,8 +195,8 @@ declare void @_ZSt9terminatev() ; CHECK-V7-FP-ELIM-LABEL: _Z4testiiiiiddddd: ; CHECK-V7-FP-ELIM: .fnstart -; CHECK-V7-FP-ELIM: .save {r4, lr} -; CHECK-V7-FP-ELIM: push {r4, lr} +; CHECK-V7-FP-ELIM: .save {r11, lr} +; CHECK-V7-FP-ELIM: push {r11, lr} ; CHECK-V7-FP-ELIM: .vsave {d8, d9, d10, d11, d12} ; CHECK-V7-FP-ELIM: vpush {d8, d9, d10, d11, d12} ; CHECK-V7-FP-ELIM: .pad #24 @@ -254,33 +254,31 @@ declare void @_ZSt9terminatev() ; DWARF-V7-FP: .cfi_startproc ; DWARF-V7-FP: .cfi_personality 0, __gxx_personality_v0 ; DWARF-V7-FP: .cfi_lsda 0, .Lexception0 -; DWARF-V7-FP: push {r4, r10, r11, lr} -; DWARF-V7-FP: .cfi_def_cfa_offset 16 +; DWARF-V7-FP: push {r11, lr} +; DWARF-V7-FP: .cfi_def_cfa_offset 8 ; DWARF-V7-FP: .cfi_offset lr, -4 ; DWARF-V7-FP: .cfi_offset r11, -8 -; DWARF-V7-FP: .cfi_offset r10, -12 -; DWARF-V7-FP: .cfi_offset r4, -16 -; DWARF-V7-FP: add r11, sp, #8 -; DWARF-V7-FP: .cfi_def_cfa r11, 8 +; DWARF-V7-FP: mov r11, sp +; DWARF-V7-FP: .cfi_def_cfa_register r11 ; DWARF-V7-FP: vpush {d8, d9, d10, d11, d12} -; DWARF-V7-FP: .cfi_offset d12, -24 -; DWARF-V7-FP: .cfi_offset d11, -32 -; DWARF-V7-FP: .cfi_offset d10, -40 -; DWARF-V7-FP: .cfi_offset d9, -48 +; DWARF-V7-FP: .cfi_offset d12, -16 +; DWARF-V7-FP: .cfi_offset d11, -24 +; DWARF-V7-FP: .cfi_offset d10, -32 +; DWARF-V7-FP: .cfi_offset d9, -40 ; DWARF-V7-FP: sub sp, sp, #24 -; DWARF-V7-FP: sub sp, r11, #48 +; DWARF-V7-FP: sub sp, r11, #40 ; DWARF-V7-FP: vpop {d8, d9, d10, d11, d12} -; DWARF-V7-FP: pop {r4, r10, r11, pc} +; DWARF-V7-FP: pop {r11, pc} ; DWARF-V7-FP: .cfi_endproc ; DWARF-V7-FP-ELIM-LABEL: _Z4testiiiiiddddd: ; DWARF-V7-FP-ELIM: .cfi_startproc ; DWARF-V7-FP-ELIM: .cfi_personality 0, __gxx_personality_v0 ; DWARF-V7-FP-ELIM: .cfi_lsda 0, .Lexception0 -; DWARF-V7-FP-ELIM: push {r4, lr} +; DWARF-V7-FP-ELIM: push {r11, lr} ; DWARF-V7-FP-ELIM: .cfi_def_cfa_offset 8 ; DWARF-V7-FP-ELIM: .cfi_offset lr, -4 -; DWARF-V7-FP-ELIM: .cfi_offset r4, -8 +; DWARF-V7-FP-ELIM: .cfi_offset r11, -8 ; DWARF-V7-FP-ELIM: vpush {d8, d9, d10, d11, d12} ; DWARF-V7-FP-ELIM: .cfi_offset d12, -16 ; DWARF-V7-FP-ELIM: .cfi_offset d11, -24 @@ -290,7 +288,7 @@ declare void @_ZSt9terminatev() ; DWARF-V7-FP-ELIM: .cfi_def_cfa_offset 72 ; DWARF-V7-FP-ELIM: add sp, sp, #24 ; DWARF-V7-FP-ELIM: vpop {d8, d9, d10, d11, d12} -; DWARF-V7-FP-ELIM: pop {r4, pc} +; DWARF-V7-FP-ELIM: pop {r11, pc} ; DWARF-V7-FP-ELIM: .cfi_endproc ; DWARF-WIN-FP-ELIM-LABEL: _Z4testiiiiiddddd: