mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-24 22:30:13 +00:00
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:
parent
93df7b9f75
commit
d8075e8781
@ -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)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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 ||
|
||||||
|
@ -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
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
32
llvm/test/CodeGen/ARM/eh-resume2.ll
Normal file
32
llvm/test/CodeGen/ARM/eh-resume2.ll
Normal 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
|
@ -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:
|
||||||
|
Loading…
Reference in New Issue
Block a user