Reland "[ARM] __cxa_end_cleanup should be called instead of _UnwindResume."

This is relanding commit da1d1a0869 .
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
This commit is contained in:
Daniel Kiss 2021-10-27 10:32:11 +02:00
parent 93df7b9f75
commit d8075e8781
9 changed files with 158 additions and 106 deletions

View File

@ -341,8 +341,10 @@ unwinding with _Unwind_Resume.
According to ARM EHABI 8.4.1, __cxa_end_cleanup() should not clobber any 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 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 {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 first argument to _Unwind_Resume(). In addition, we are saving lr in order to
align the stack to 16 bytes, even though it is a callee-save register. 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 * __attribute__((used)) static _Unwind_Exception *
__cxa_end_cleanup_impl() __cxa_end_cleanup_impl()
@ -372,18 +374,16 @@ __cxa_end_cleanup_impl()
return &exception_header->unwindHeader; return &exception_header->unwindHeader;
} }
asm ( asm(" .pushsection .text.__cxa_end_cleanup,\"ax\",%progbits\n"
" .pushsection .text.__cxa_end_cleanup,\"ax\",%progbits\n"
" .globl __cxa_end_cleanup\n" " .globl __cxa_end_cleanup\n"
" .type __cxa_end_cleanup,%function\n" " .type __cxa_end_cleanup,%function\n"
"__cxa_end_cleanup:\n" "__cxa_end_cleanup:\n"
" push {r1, r2, r3, r4}\n" " push {r1, r2, r3, lr}\n"
" bl __cxa_end_cleanup_impl\n" " bl __cxa_end_cleanup_impl\n"
" pop {r1, r2, r3, r4}\n" " pop {r1, r2, r3, r4}\n"
" bl _Unwind_Resume\n" " mov lr, r4\n"
" bl abort\n" " b _Unwind_Resume\n"
" .popsection" " .popsection");
);
#endif // defined(_LIBCXXABI_ARM_EHABI) #endif // defined(_LIBCXXABI_ARM_EHABI)
/* /*

View File

@ -721,6 +721,19 @@ public:
return getArch() == Triple::arm || getArch() == Triple::armeb; 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). /// Tests whether the target is AArch64 (little and big endian).
bool isAArch64() const { bool isAArch64() const {
return getArch() == Triple::aarch64 || getArch() == Triple::aarch64_be || return getArch() == Triple::aarch64 || getArch() == Triple::aarch64_be ||

View File

@ -432,6 +432,7 @@ HANDLE_LIBCALL(MEMSET_ELEMENT_UNORDERED_ATOMIC_16, "__llvm_memset_element_unorde
// Exception handling // Exception handling
HANDLE_LIBCALL(UNWIND_RESUME, "_Unwind_Resume") HANDLE_LIBCALL(UNWIND_RESUME, "_Unwind_Resume")
HANDLE_LIBCALL(CXA_END_CLEANUP, "__cxa_end_cleanup")
// Note: there are two sets of atomics libcalls; see // Note: there are two sets of atomics libcalls; see
// <https://llvm.org/docs/Atomics.html> for more info on the // <https://llvm.org/docs/Atomics.html> for more info on the

View File

@ -14,6 +14,7 @@
#include "llvm/ADT/BitVector.h" #include "llvm/ADT/BitVector.h"
#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h" #include "llvm/ADT/Statistic.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/CFG.h" #include "llvm/Analysis/CFG.h"
#include "llvm/Analysis/DomTreeUpdater.h" #include "llvm/Analysis/DomTreeUpdater.h"
#include "llvm/Analysis/EHPersonalities.h" #include "llvm/Analysis/EHPersonalities.h"
@ -54,13 +55,11 @@ namespace {
class DwarfEHPrepare { class DwarfEHPrepare {
CodeGenOpt::Level OptLevel; CodeGenOpt::Level OptLevel;
// RewindFunction - _Unwind_Resume or the target equivalent.
FunctionCallee &RewindFunction;
Function &F; Function &F;
const TargetLowering &TLI; const TargetLowering &TLI;
DomTreeUpdater *DTU; DomTreeUpdater *DTU;
const TargetTransformInfo *TTI; const TargetTransformInfo *TTI;
const Triple &TargetTriple;
/// Return the exception object from the value passed into /// Return the exception object from the value passed into
/// the 'resume' instruction (typically an aggregate). Clean up any dead /// the 'resume' instruction (typically an aggregate). Clean up any dead
@ -78,11 +77,11 @@ class DwarfEHPrepare {
bool InsertUnwindResumeCalls(); bool InsertUnwindResumeCalls();
public: public:
DwarfEHPrepare(CodeGenOpt::Level OptLevel_, FunctionCallee &RewindFunction_, DwarfEHPrepare(CodeGenOpt::Level OptLevel_, Function &F_,
Function &F_, const TargetLowering &TLI_, DomTreeUpdater *DTU_, const TargetLowering &TLI_, DomTreeUpdater *DTU_,
const TargetTransformInfo *TTI_) const TargetTransformInfo *TTI_, const Triple &TargetTriple_)
: OptLevel(OptLevel_), RewindFunction(RewindFunction_), F(F_), TLI(TLI_), : OptLevel(OptLevel_), F(F_), TLI(TLI_), DTU(DTU_), TTI(TTI_),
DTU(DTU_), TTI(TTI_) {} TargetTriple(TargetTriple_) {}
bool run(); bool run();
}; };
@ -211,13 +210,28 @@ bool DwarfEHPrepare::InsertUnwindResumeCalls() {
if (ResumesLeft == 0) if (ResumesLeft == 0)
return true; // We pruned them all. return true; // We pruned them all.
// Find the rewind function if we didn't already. // RewindFunction - _Unwind_Resume or the target equivalent.
if (!RewindFunction) { FunctionCallee RewindFunction;
FunctionType *FTy = 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); FunctionType::get(Type::getVoidTy(Ctx), Type::getInt8PtrTy(Ctx), false);
const char *RewindName = TLI.getLibcallName(RTLIB::UNWIND_RESUME); RewindFunctionCallingConv = TLI.getLibcallCallingConv(RTLIB::UNWIND_RESUME);
RewindFunction = F.getParent()->getOrInsertFunction(RewindName, FTy); DoesRewindFunctionNeedExceptionObject = true;
} }
RewindFunction = F.getParent()->getOrInsertFunction(RewindName, FTy);
// Create the basic block where the _Unwind_Resume call will live. // Create the basic block where the _Unwind_Resume call will live.
if (ResumesLeft == 1) { if (ResumesLeft == 1) {
@ -226,10 +240,14 @@ bool DwarfEHPrepare::InsertUnwindResumeCalls() {
ResumeInst *RI = Resumes.front(); ResumeInst *RI = Resumes.front();
BasicBlock *UnwindBB = RI->getParent(); BasicBlock *UnwindBB = RI->getParent();
Value *ExnObj = GetExceptionObject(RI); Value *ExnObj = GetExceptionObject(RI);
llvm::SmallVector<Value *, 1> RewindFunctionArgs;
if (DoesRewindFunctionNeedExceptionObject)
RewindFunctionArgs.push_back(ExnObj);
// Call the _Unwind_Resume function. // Call the rewind function.
CallInst *CI = CallInst::Create(RewindFunction, ExnObj, "", UnwindBB); CallInst *CI =
CI->setCallingConv(TLI.getLibcallCallingConv(RTLIB::UNWIND_RESUME)); CallInst::Create(RewindFunction, RewindFunctionArgs, "", UnwindBB);
CI->setCallingConv(RewindFunctionCallingConv);
// We never expect _Unwind_Resume to return. // We never expect _Unwind_Resume to return.
CI->setDoesNotReturn(); CI->setDoesNotReturn();
@ -240,6 +258,8 @@ bool DwarfEHPrepare::InsertUnwindResumeCalls() {
std::vector<DominatorTree::UpdateType> Updates; std::vector<DominatorTree::UpdateType> Updates;
Updates.reserve(Resumes.size()); Updates.reserve(Resumes.size());
llvm::SmallVector<Value *, 1> RewindFunctionArgs;
BasicBlock *UnwindBB = BasicBlock::Create(Ctx, "unwind_resume", &F); BasicBlock *UnwindBB = BasicBlock::Create(Ctx, "unwind_resume", &F);
PHINode *PN = PHINode::Create(Type::getInt8PtrTy(Ctx), ResumesLeft, "exn.obj", PHINode *PN = PHINode::Create(Type::getInt8PtrTy(Ctx), ResumesLeft, "exn.obj",
UnwindBB); UnwindBB);
@ -257,9 +277,13 @@ bool DwarfEHPrepare::InsertUnwindResumeCalls() {
++NumResumesLowered; ++NumResumesLowered;
} }
if (DoesRewindFunctionNeedExceptionObject)
RewindFunctionArgs.push_back(PN);
// Call the function. // Call the function.
CallInst *CI = CallInst::Create(RewindFunction, PN, "", UnwindBB); CallInst *CI =
CI->setCallingConv(TLI.getLibcallCallingConv(RTLIB::UNWIND_RESUME)); CallInst::Create(RewindFunction, RewindFunctionArgs, "", UnwindBB);
CI->setCallingConv(RewindFunctionCallingConv);
// We never expect _Unwind_Resume to return. // We never expect _Unwind_Resume to return.
CI->setDoesNotReturn(); CI->setDoesNotReturn();
@ -277,22 +301,20 @@ bool DwarfEHPrepare::run() {
return Changed; return Changed;
} }
static bool prepareDwarfEH(CodeGenOpt::Level OptLevel, static bool prepareDwarfEH(CodeGenOpt::Level OptLevel, Function &F,
FunctionCallee &RewindFunction, Function &F,
const TargetLowering &TLI, DominatorTree *DT, const TargetLowering &TLI, DominatorTree *DT,
const TargetTransformInfo *TTI) { const TargetTransformInfo *TTI,
const Triple &TargetTriple) {
DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy); DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
return DwarfEHPrepare(OptLevel, RewindFunction, F, TLI, DT ? &DTU : nullptr, return DwarfEHPrepare(OptLevel, F, TLI, DT ? &DTU : nullptr, TTI,
TTI) TargetTriple)
.run(); .run();
} }
namespace { namespace {
class DwarfEHPrepareLegacyPass : public FunctionPass { class DwarfEHPrepareLegacyPass : public FunctionPass {
// RewindFunction - _Unwind_Resume or the target equivalent.
FunctionCallee RewindFunction = nullptr;
CodeGenOpt::Level OptLevel; CodeGenOpt::Level OptLevel;
@ -315,12 +337,7 @@ public:
DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F); TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
} }
return prepareDwarfEH(OptLevel, RewindFunction, F, TLI, DT, TTI); return prepareDwarfEH(OptLevel, F, TLI, DT, TTI, TM.getTargetTriple());
}
bool doFinalization(Module &M) override {
RewindFunction = nullptr;
return false;
} }
void getAnalysisUsage(AnalysisUsage &AU) const override { void getAnalysisUsage(AnalysisUsage &AU) const override {

View File

@ -792,14 +792,7 @@ public:
// ARM Targets that support EHABI exception handling standard // ARM Targets that support EHABI exception handling standard
// Darwin uses SjLj. Other targets might need more checks. // Darwin uses SjLj. Other targets might need more checks.
bool isTargetEHABICompatible() const { bool isTargetEHABICompatible() const {
return (TargetTriple.getEnvironment() == Triple::EABI || return TargetTriple.isTargetEHABICompatible();
TargetTriple.getEnvironment() == Triple::GNUEABI ||
TargetTriple.getEnvironment() == Triple::MuslEABI ||
TargetTriple.getEnvironment() == Triple::EABIHF ||
TargetTriple.getEnvironment() == Triple::GNUEABIHF ||
TargetTriple.getEnvironment() == Triple::MuslEABIHF ||
isTargetAndroid()) &&
!isTargetDarwin() && !isTargetWindows();
} }
bool isTargetHardFloat() const; bool isTargetHardFloat() const;

View File

@ -197,29 +197,27 @@ declare void @_ZSt9terminatev()
; CHECK-V7-FP-LABEL: _Z4testiiiiiddddd: ; CHECK-V7-FP-LABEL: _Z4testiiiiiddddd:
; CHECK-V7-FP: .cfi_startproc ; CHECK-V7-FP: .cfi_startproc
; CHECK-V7-FP: push {r4, r10, r11, lr} ; CHECK-V7-FP: push {r11, lr}
; CHECK-V7-FP: .cfi_def_cfa_offset 16 ; CHECK-V7-FP: .cfi_def_cfa_offset 8
; CHECK-V7-FP: .cfi_offset lr, -4 ; CHECK-V7-FP: .cfi_offset lr, -4
; CHECK-V7-FP: .cfi_offset r11, -8 ; CHECK-V7-FP: .cfi_offset r11, -8
; CHECK-V7-FP: .cfi_offset r10, -12 ; CHECK-V7-FP: mov r11, sp
; CHECK-V7-FP: .cfi_offset r4, -16 ; CHECK-V7-FP: .cfi_def_cfa_register r11
; CHECK-V7-FP: add r11, sp, #8
; CHECK-V7-FP: .cfi_def_cfa r11, 8
; CHECK-V7-FP: vpush {d8, d9, d10, d11, d12} ; CHECK-V7-FP: vpush {d8, d9, d10, d11, d12}
; CHECK-V7-FP: .cfi_offset d12, -24 ; CHECK-V7-FP: .cfi_offset d12, -16
; CHECK-V7-FP: .cfi_offset d11, -32 ; CHECK-V7-FP: .cfi_offset d11, -24
; CHECK-V7-FP: .cfi_offset d10, -40 ; CHECK-V7-FP: .cfi_offset d10, -32
; CHECK-V7-FP: .cfi_offset d9, -48 ; CHECK-V7-FP: .cfi_offset d9, -40
; CHECK-V7-FP: .cfi_offset d8, -56 ; CHECK-V7-FP: .cfi_offset d8, -48
; CHECK-V7-FP: sub sp, sp, #24 ; CHECK-V7-FP: sub sp, sp, #24
; CHECK-V7-FP: .cfi_endproc ; CHECK-V7-FP: .cfi_endproc
; CHECK-V7-FP-ELIM-LABEL: _Z4testiiiiiddddd: ; CHECK-V7-FP-ELIM-LABEL: _Z4testiiiiiddddd:
; CHECK-V7-FP-ELIM: .cfi_startproc ; 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_def_cfa_offset 8
; CHECK-V7-FP-ELIM: .cfi_offset lr, -4 ; 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: vpush {d8, d9, d10, d11, d12}
; CHECK-V7-FP-ELIM: .cfi_def_cfa_offset 48 ; CHECK-V7-FP-ELIM: .cfi_def_cfa_offset 48
; CHECK-V7-FP-ELIM: .cfi_offset d12, -16 ; 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-LABEL: _Z4testiiiiiddddd:
; CHECK-THUMB-V7-FP: .cfi_startproc ; CHECK-THUMB-V7-FP: .cfi_startproc
; CHECK-THUMB-V7-FP: push {r4, r6, r7, lr} ; CHECK-THUMB-V7-FP: push {r7, lr}
; CHECK-THUMB-V7-FP: .cfi_def_cfa_offset 16 ; CHECK-THUMB-V7-FP: .cfi_def_cfa_offset 8
; CHECK-THUMB-V7-FP: .cfi_offset lr, -4 ; CHECK-THUMB-V7-FP: .cfi_offset lr, -4
; CHECK-THUMB-V7-FP: .cfi_offset r7, -8 ; CHECK-THUMB-V7-FP: .cfi_offset r7, -8
; CHECK-THUMB-V7-FP: .cfi_offset r6, -12 ; CHECK-THUMB-V7-FP: mov r7, sp
; CHECK-THUMB-V7-FP: .cfi_offset r4, -16 ; CHECK-THUMB-V7-FP: .cfi_def_cfa_register r7
; CHECK-THUMB-V7-FP: add r7, sp, #8
; CHECK-THUMB-V7-FP: .cfi_def_cfa r7, 8
; CHECK-THUMB-V7-FP: vpush {d8, d9, d10, d11, d12} ; CHECK-THUMB-V7-FP: vpush {d8, d9, d10, d11, d12}
; CHECK-THUMB-V7-FP: .cfi_offset d12, -24 ; CHECK-THUMB-V7-FP: .cfi_offset d12, -16
; CHECK-THUMB-V7-FP: .cfi_offset d11, -32 ; CHECK-THUMB-V7-FP: .cfi_offset d11, -24
; CHECK-THUMB-V7-FP: .cfi_offset d10, -40 ; CHECK-THUMB-V7-FP: .cfi_offset d10, -32
; CHECK-THUMB-V7-FP: .cfi_offset d9, -48 ; CHECK-THUMB-V7-FP: .cfi_offset d9, -40
; CHECK-THUMB-V7-FP: .cfi_offset d8, -56 ; CHECK-THUMB-V7-FP: .cfi_offset d8, -48
; CHECK-THUMB-V7-FP: sub sp, #24 ; CHECK-THUMB-V7-FP: sub sp, #24
; CHECK-THUMB-V7-FP: .cfi_endproc ; CHECK-THUMB-V7-FP: .cfi_endproc
; CHECK-THUMB-V7-FP-ELIM-LABEL: _Z4testiiiiiddddd: ; CHECK-THUMB-V7-FP-ELIM-LABEL: _Z4testiiiiiddddd:
; CHECK-THUMB-V7-FP-ELIM: .cfi_startproc ; 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_def_cfa_offset 8
; CHECK-THUMB-V7-FP-ELIM: .cfi_offset lr, -4 ; 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: vpush {d8, d9, d10, d11, d12}
; CHECK-THUMB-V7-FP-ELIM: .cfi_def_cfa_offset 48 ; CHECK-THUMB-V7-FP-ELIM: .cfi_def_cfa_offset 48
; CHECK-THUMB-V7-FP-ELIM: .cfi_offset d12, -16 ; 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-LABEL: _Z4testiiiiiddddd:
; CHECK-THUMB-V7-FP-NOIAS: .cfi_startproc ; CHECK-THUMB-V7-FP-NOIAS: .cfi_startproc
; CHECK-THUMB-V7-FP-NOIAS: push {r4, r6, r7, lr} ; CHECK-THUMB-V7-FP-NOIAS: push {r7, lr}
; CHECK-THUMB-V7-FP-NOIAS: .cfi_def_cfa_offset 16 ; 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 14, -4
; CHECK-THUMB-V7-FP-NOIAS: .cfi_offset 7, -8 ; CHECK-THUMB-V7-FP-NOIAS: .cfi_offset 7, -8
; CHECK-THUMB-V7-FP-NOIAS: .cfi_offset 6, -12 ; CHECK-THUMB-V7-FP-NOIAS: mov r7, sp
; CHECK-THUMB-V7-FP-NOIAS: .cfi_offset 4, -16 ; CHECK-THUMB-V7-FP-NOIAS: .cfi_def_cfa_register 7
; CHECK-THUMB-V7-FP-NOIAS: add r7, sp, #8
; CHECK-THUMB-V7-FP-NOIAS: .cfi_def_cfa 7, 8
; CHECK-THUMB-V7-FP-NOIAS: vpush {d8, d9, d10, d11, d12} ; 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 268, -16
; CHECK-THUMB-V7-FP-NOIAS: .cfi_offset 267, -32 ; CHECK-THUMB-V7-FP-NOIAS: .cfi_offset 267, -24
; CHECK-THUMB-V7-FP-NOIAS: .cfi_offset 266, -40 ; CHECK-THUMB-V7-FP-NOIAS: .cfi_offset 266, -32
; CHECK-THUMB-V7-FP-NOIAS: .cfi_offset 265, -48 ; CHECK-THUMB-V7-FP-NOIAS: .cfi_offset 265, -40
; CHECK-THUMB-V7-FP-NOIAS: .cfi_offset 264, -56 ; CHECK-THUMB-V7-FP-NOIAS: .cfi_offset 264, -48
; CHECK-THUMB-V7-FP-NOIAS: sub sp, #24 ; CHECK-THUMB-V7-FP-NOIAS: sub sp, #24
; CHECK-THUMB-V7-FP-NOIAS: .cfi_endproc ; CHECK-THUMB-V7-FP-NOIAS: .cfi_endproc

View File

@ -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=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-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=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() declare void @func()
@ -23,3 +25,5 @@ lpad:
; IOS: __Unwind_SjLj_Resume ; IOS: __Unwind_SjLj_Resume
; WATCHABI: __Unwind_Resume ; WATCHABI: __Unwind_Resume
; EABI: __cxa_end_cleanup
; ABI: _Unwind_Resume

View File

@ -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

View File

@ -181,10 +181,10 @@ declare void @_ZSt9terminatev()
; CHECK-V7-FP-LABEL: _Z4testiiiiiddddd: ; CHECK-V7-FP-LABEL: _Z4testiiiiiddddd:
; CHECK-V7-FP: .fnstart ; CHECK-V7-FP: .fnstart
; CHECK-V7-FP: .save {r4, r10, r11, lr} ; CHECK-V7-FP: .save {r11, lr}
; CHECK-V7-FP: push {r4, r10, r11, lr} ; CHECK-V7-FP: push {r11, lr}
; CHECK-V7-FP: .setfp r11, sp, #8 ; CHECK-V7-FP: .setfp r11, sp
; CHECK-V7-FP: add r11, sp, #8 ; CHECK-V7-FP: mov r11, sp
; CHECK-V7-FP: .vsave {d8, d9, d10, d11, d12} ; CHECK-V7-FP: .vsave {d8, d9, d10, d11, d12}
; CHECK-V7-FP: vpush {d8, d9, d10, d11, d12} ; CHECK-V7-FP: vpush {d8, d9, d10, d11, d12}
; CHECK-V7-FP: .pad #24 ; CHECK-V7-FP: .pad #24
@ -195,8 +195,8 @@ declare void @_ZSt9terminatev()
; CHECK-V7-FP-ELIM-LABEL: _Z4testiiiiiddddd: ; CHECK-V7-FP-ELIM-LABEL: _Z4testiiiiiddddd:
; CHECK-V7-FP-ELIM: .fnstart ; CHECK-V7-FP-ELIM: .fnstart
; CHECK-V7-FP-ELIM: .save {r4, lr} ; CHECK-V7-FP-ELIM: .save {r11, lr}
; CHECK-V7-FP-ELIM: push {r4, lr} ; CHECK-V7-FP-ELIM: push {r11, lr}
; CHECK-V7-FP-ELIM: .vsave {d8, d9, d10, d11, d12} ; CHECK-V7-FP-ELIM: .vsave {d8, d9, d10, d11, d12}
; CHECK-V7-FP-ELIM: vpush {d8, d9, d10, d11, d12} ; CHECK-V7-FP-ELIM: vpush {d8, d9, d10, d11, d12}
; CHECK-V7-FP-ELIM: .pad #24 ; CHECK-V7-FP-ELIM: .pad #24
@ -254,33 +254,31 @@ declare void @_ZSt9terminatev()
; DWARF-V7-FP: .cfi_startproc ; DWARF-V7-FP: .cfi_startproc
; DWARF-V7-FP: .cfi_personality 0, __gxx_personality_v0 ; DWARF-V7-FP: .cfi_personality 0, __gxx_personality_v0
; DWARF-V7-FP: .cfi_lsda 0, .Lexception0 ; DWARF-V7-FP: .cfi_lsda 0, .Lexception0
; DWARF-V7-FP: push {r4, r10, r11, lr} ; DWARF-V7-FP: push {r11, lr}
; DWARF-V7-FP: .cfi_def_cfa_offset 16 ; DWARF-V7-FP: .cfi_def_cfa_offset 8
; DWARF-V7-FP: .cfi_offset lr, -4 ; DWARF-V7-FP: .cfi_offset lr, -4
; DWARF-V7-FP: .cfi_offset r11, -8 ; DWARF-V7-FP: .cfi_offset r11, -8
; DWARF-V7-FP: .cfi_offset r10, -12 ; DWARF-V7-FP: mov r11, sp
; DWARF-V7-FP: .cfi_offset r4, -16 ; DWARF-V7-FP: .cfi_def_cfa_register r11
; DWARF-V7-FP: add r11, sp, #8
; DWARF-V7-FP: .cfi_def_cfa r11, 8
; DWARF-V7-FP: vpush {d8, d9, d10, d11, d12} ; DWARF-V7-FP: vpush {d8, d9, d10, d11, d12}
; DWARF-V7-FP: .cfi_offset d12, -24 ; DWARF-V7-FP: .cfi_offset d12, -16
; DWARF-V7-FP: .cfi_offset d11, -32 ; DWARF-V7-FP: .cfi_offset d11, -24
; DWARF-V7-FP: .cfi_offset d10, -40 ; DWARF-V7-FP: .cfi_offset d10, -32
; DWARF-V7-FP: .cfi_offset d9, -48 ; DWARF-V7-FP: .cfi_offset d9, -40
; DWARF-V7-FP: sub sp, sp, #24 ; 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: 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: .cfi_endproc
; DWARF-V7-FP-ELIM-LABEL: _Z4testiiiiiddddd: ; DWARF-V7-FP-ELIM-LABEL: _Z4testiiiiiddddd:
; DWARF-V7-FP-ELIM: .cfi_startproc ; DWARF-V7-FP-ELIM: .cfi_startproc
; DWARF-V7-FP-ELIM: .cfi_personality 0, __gxx_personality_v0 ; DWARF-V7-FP-ELIM: .cfi_personality 0, __gxx_personality_v0
; DWARF-V7-FP-ELIM: .cfi_lsda 0, .Lexception0 ; 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_def_cfa_offset 8
; DWARF-V7-FP-ELIM: .cfi_offset lr, -4 ; 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: vpush {d8, d9, d10, d11, d12}
; DWARF-V7-FP-ELIM: .cfi_offset d12, -16 ; DWARF-V7-FP-ELIM: .cfi_offset d12, -16
; DWARF-V7-FP-ELIM: .cfi_offset d11, -24 ; 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: .cfi_def_cfa_offset 72
; DWARF-V7-FP-ELIM: add sp, sp, #24 ; DWARF-V7-FP-ELIM: add sp, sp, #24
; DWARF-V7-FP-ELIM: vpop {d8, d9, d10, d11, d12} ; 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-V7-FP-ELIM: .cfi_endproc
; DWARF-WIN-FP-ELIM-LABEL: _Z4testiiiiiddddd: ; DWARF-WIN-FP-ELIM-LABEL: _Z4testiiiiiddddd: