Index: libcxxabi/src/cxa_exception.cpp =================================================================== --- libcxxabi/src/cxa_exception.cpp +++ libcxxabi/src/cxa_exception.cpp @@ -341,8 +341,9 @@ 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 +373,15 @@ 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" -); + " pop {r1, r2, r3, lr}\n" + " b _Unwind_Resume\n" + " .popsection"); #endif // defined(_LIBCXXABI_ARM_EHABI) /* Index: llvm/lib/CodeGen/DwarfEHPrepare.cpp =================================================================== --- llvm/lib/CodeGen/DwarfEHPrepare.cpp +++ 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" @@ -61,6 +62,7 @@ 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 @@ -77,12 +79,23 @@ /// into calls to the appropriate _Unwind_Resume function. bool InsertUnwindResumeCalls(); + bool isTargetEHABICompatible(Triple TargetTriple) 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 || + TargetTriple.isAndroid()) && + !TargetTriple.isOSDarwin() && !TargetTriple.isOSWindows(); + } + public: DwarfEHPrepare(CodeGenOpt::Level OptLevel_, FunctionCallee &RewindFunction_, Function &F_, const TargetLowering &TLI_, DomTreeUpdater *DTU_, - const TargetTransformInfo *TTI_) + const TargetTransformInfo *TTI_, const Triple &TargetTriple_) : OptLevel(OptLevel_), RewindFunction(RewindFunction_), F(F_), TLI(TLI_), - DTU(DTU_), TTI(TTI_) {} + DTU(DTU_), TTI(TTI_), TargetTriple(TargetTriple_) {} bool run(); }; @@ -215,7 +228,14 @@ if (!RewindFunction) { FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx), Type::getInt8PtrTy(Ctx), false); - const char *RewindName = TLI.getLibcallName(RTLIB::UNWIND_RESUME); + const char *RewindName; + + if ((Pers == EHPersonality::GNU_CXX || + Pers == EHPersonality::GNU_CXX_SjLj) && + isTargetEHABICompatible(TargetTriple)) + RewindName = "__cxa_end_cleanup"; + else + RewindName = TLI.getLibcallName(RTLIB::UNWIND_RESUME); RewindFunction = F.getParent()->getOrInsertFunction(RewindName, FTy); } @@ -280,11 +300,12 @@ static bool prepareDwarfEH(CodeGenOpt::Level OptLevel, FunctionCallee &RewindFunction, 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) + TTI, TargetTriple) .run(); } @@ -315,7 +336,8 @@ DT = &getAnalysis().getDomTree(); TTI = &getAnalysis().getTTI(F); } - return prepareDwarfEH(OptLevel, RewindFunction, F, TLI, DT, TTI); + return prepareDwarfEH(OptLevel, RewindFunction, F, TLI, DT, TTI, + TM.getTargetTriple()); } bool doFinalization(Module &M) override { Index: llvm/test/CodeGen/ARM/eh-resume.ll =================================================================== --- llvm/test/CodeGen/ARM/eh-resume.ll +++ 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 @@ ; IOS: __Unwind_SjLj_Resume ; WATCHABI: __Unwind_Resume +; EABI: __cxa_end_cleanup +; ABI: _Unwind_Resume Index: llvm/test/CodeGen/ARM/eh-resume2.ll =================================================================== --- /dev/null +++ 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