diff options
Diffstat (limited to 'clang/lib/CIR/CodeGen/CIRGenException.cpp')
| -rw-r--r-- | clang/lib/CIR/CodeGen/CIRGenException.cpp | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/clang/lib/CIR/CodeGen/CIRGenException.cpp b/clang/lib/CIR/CodeGen/CIRGenException.cpp index 717a3e0..67f46ff 100644 --- a/clang/lib/CIR/CodeGen/CIRGenException.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenException.cpp @@ -18,6 +18,171 @@ using namespace clang; using namespace clang::CIRGen; +const EHPersonality EHPersonality::GNU_C = {"__gcc_personality_v0", nullptr}; +const EHPersonality EHPersonality::GNU_C_SJLJ = {"__gcc_personality_sj0", + nullptr}; +const EHPersonality EHPersonality::GNU_C_SEH = {"__gcc_personality_seh0", + nullptr}; +const EHPersonality EHPersonality::NeXT_ObjC = {"__objc_personality_v0", + nullptr}; +const EHPersonality EHPersonality::GNU_CPlusPlus = {"__gxx_personality_v0", + nullptr}; +const EHPersonality EHPersonality::GNU_CPlusPlus_SJLJ = { + "__gxx_personality_sj0", nullptr}; +const EHPersonality EHPersonality::GNU_CPlusPlus_SEH = { + "__gxx_personality_seh0", nullptr}; +const EHPersonality EHPersonality::GNU_ObjC = {"__gnu_objc_personality_v0", + "objc_exception_throw"}; +const EHPersonality EHPersonality::GNU_ObjC_SJLJ = { + "__gnu_objc_personality_sj0", "objc_exception_throw"}; +const EHPersonality EHPersonality::GNU_ObjC_SEH = { + "__gnu_objc_personality_seh0", "objc_exception_throw"}; +const EHPersonality EHPersonality::GNU_ObjCXX = { + "__gnustep_objcxx_personality_v0", nullptr}; +const EHPersonality EHPersonality::GNUstep_ObjC = { + "__gnustep_objc_personality_v0", nullptr}; +const EHPersonality EHPersonality::MSVC_except_handler = {"_except_handler3", + nullptr}; +const EHPersonality EHPersonality::MSVC_C_specific_handler = { + "__C_specific_handler", nullptr}; +const EHPersonality EHPersonality::MSVC_CxxFrameHandler3 = { + "__CxxFrameHandler3", nullptr}; +const EHPersonality EHPersonality::GNU_Wasm_CPlusPlus = { + "__gxx_wasm_personality_v0", nullptr}; +const EHPersonality EHPersonality::XL_CPlusPlus = {"__xlcxx_personality_v1", + nullptr}; +const EHPersonality EHPersonality::ZOS_CPlusPlus = {"__zos_cxx_personality_v2", + nullptr}; + +static const EHPersonality &getCPersonality(const TargetInfo &target, + const CodeGenOptions &cgOpts) { + const llvm::Triple &triple = target.getTriple(); + if (triple.isWindowsMSVCEnvironment()) + return EHPersonality::MSVC_CxxFrameHandler3; + if (cgOpts.hasSjLjExceptions()) + return EHPersonality::GNU_C_SJLJ; + if (cgOpts.hasDWARFExceptions()) + return EHPersonality::GNU_C; + if (cgOpts.hasSEHExceptions()) + return EHPersonality::GNU_C_SEH; + return EHPersonality::GNU_C; +} + +static const EHPersonality &getObjCPersonality(const TargetInfo &target, + const LangOptions &langOpts, + const CodeGenOptions &cgOpts) { + const llvm::Triple &triple = target.getTriple(); + if (triple.isWindowsMSVCEnvironment()) + return EHPersonality::MSVC_CxxFrameHandler3; + + switch (langOpts.ObjCRuntime.getKind()) { + case ObjCRuntime::FragileMacOSX: + return getCPersonality(target, cgOpts); + case ObjCRuntime::MacOSX: + case ObjCRuntime::iOS: + case ObjCRuntime::WatchOS: + return EHPersonality::NeXT_ObjC; + case ObjCRuntime::GNUstep: + if (langOpts.ObjCRuntime.getVersion() >= VersionTuple(1, 7)) + return EHPersonality::GNUstep_ObjC; + [[fallthrough]]; + case ObjCRuntime::GCC: + case ObjCRuntime::ObjFW: + if (cgOpts.hasSjLjExceptions()) + return EHPersonality::GNU_ObjC_SJLJ; + if (cgOpts.hasSEHExceptions()) + return EHPersonality::GNU_ObjC_SEH; + return EHPersonality::GNU_ObjC; + } + llvm_unreachable("bad runtime kind"); +} + +static const EHPersonality &getCXXPersonality(const TargetInfo &target, + const CodeGenOptions &cgOpts) { + const llvm::Triple &triple = target.getTriple(); + if (triple.isWindowsMSVCEnvironment()) + return EHPersonality::MSVC_CxxFrameHandler3; + if (triple.isOSAIX()) + return EHPersonality::XL_CPlusPlus; + if (cgOpts.hasSjLjExceptions()) + return EHPersonality::GNU_CPlusPlus_SJLJ; + if (cgOpts.hasDWARFExceptions()) + return EHPersonality::GNU_CPlusPlus; + if (cgOpts.hasSEHExceptions()) + return EHPersonality::GNU_CPlusPlus_SEH; + if (cgOpts.hasWasmExceptions()) + return EHPersonality::GNU_Wasm_CPlusPlus; + return EHPersonality::GNU_CPlusPlus; +} + +/// Determines the personality function to use when both C++ +/// and Objective-C exceptions are being caught. +static const EHPersonality &getObjCXXPersonality(const TargetInfo &target, + const LangOptions &langOpts, + const CodeGenOptions &cgOpts) { + if (target.getTriple().isWindowsMSVCEnvironment()) + return EHPersonality::MSVC_CxxFrameHandler3; + + switch (langOpts.ObjCRuntime.getKind()) { + // In the fragile ABI, just use C++ exception handling and hope + // they're not doing crazy exception mixing. + case ObjCRuntime::FragileMacOSX: + return getCXXPersonality(target, cgOpts); + + // The ObjC personality defers to the C++ personality for non-ObjC + // handlers. Unlike the C++ case, we use the same personality + // function on targets using (backend-driven) SJLJ EH. + case ObjCRuntime::MacOSX: + case ObjCRuntime::iOS: + case ObjCRuntime::WatchOS: + return getObjCPersonality(target, langOpts, cgOpts); + + case ObjCRuntime::GNUstep: + return EHPersonality::GNU_ObjCXX; + + // The GCC runtime's personality function inherently doesn't support + // mixed EH. Use the ObjC personality just to avoid returning null. + case ObjCRuntime::GCC: + case ObjCRuntime::ObjFW: + return getObjCPersonality(target, langOpts, cgOpts); + } + llvm_unreachable("bad runtime kind"); +} + +static const EHPersonality &getSEHPersonalityMSVC(const llvm::Triple &triple) { + return triple.getArch() == llvm::Triple::x86 + ? EHPersonality::MSVC_except_handler + : EHPersonality::MSVC_C_specific_handler; +} + +const EHPersonality &EHPersonality::get(CIRGenModule &cgm, + const FunctionDecl *fd) { + const llvm::Triple &triple = cgm.getTarget().getTriple(); + const LangOptions &langOpts = cgm.getLangOpts(); + const CodeGenOptions &cgOpts = cgm.getCodeGenOpts(); + const TargetInfo &target = cgm.getTarget(); + + // Functions using SEH get an SEH personality. + if (fd && fd->usesSEHTry()) + return getSEHPersonalityMSVC(triple); + + if (langOpts.ObjC) { + return langOpts.CPlusPlus ? getObjCXXPersonality(target, langOpts, cgOpts) + : getObjCPersonality(target, langOpts, cgOpts); + } + return langOpts.CPlusPlus ? getCXXPersonality(target, cgOpts) + : getCPersonality(target, cgOpts); +} + +const EHPersonality &EHPersonality::get(CIRGenFunction &cgf) { + const auto *fg = cgf.curCodeDecl; + // For outlined finallys and filters, use the SEH personality in case they + // contain more SEH. This mostly only affects finallys. Filters could + // hypothetically use gnu statement expressions to sneak in nested SEH. + fg = fg ? fg : cgf.curSEHParent.getDecl(); + return get(cgf.cgm, dyn_cast_or_null<FunctionDecl>(fg)); +} + void CIRGenFunction::emitCXXThrowExpr(const CXXThrowExpr *e) { const llvm::Triple &triple = getTarget().getTriple(); if (cgm.getLangOpts().OpenMPIsTargetDevice && |
