1756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson//===--- CGException.cpp - Emit LLVM Code for C++ exceptions --------------===// 2756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson// 3756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson// The LLVM Compiler Infrastructure 4756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson// 5756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson// This file is distributed under the University of Illinois Open Source 6756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson// License. See LICENSE.TXT for details. 7756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson// 8756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson//===----------------------------------------------------------------------===// 9756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson// 10756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson// This contains code dealing with C++ exception related code generation. 11756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson// 12756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson//===----------------------------------------------------------------------===// 13756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson 14756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson#include "CodeGenFunction.h" 1536f893c1efe367f929d92c8b125f964c22ba189eJohn McCall#include "CGCleanup.h" 16af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer#include "CGObjCRuntime.h" 17204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall#include "TargetInfo.h" 18af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer#include "clang/AST/StmtCXX.h" 19b1ba0efc3d1dc1daa5d82c40bc504e1f368c4fa0Chandler Carruth#include "clang/AST/StmtObjC.h" 20651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines#include "llvm/IR/CallSite.h" 213b844ba7d5be205a9b4f5f0b0d1b7978977f4b8cChandler Carruth#include "llvm/IR/Intrinsics.h" 22f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 23756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlssonusing namespace clang; 24756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlssonusing namespace CodeGen; 25756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson 26629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCallstatic llvm::Constant *getAllocateExceptionFn(CodeGenModule &CGM) { 27d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson // void *__cxa_allocate_exception(size_t thrown_size); 288755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 292acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::FunctionType *FTy = 30629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCall llvm::FunctionType::get(CGM.Int8PtrTy, CGM.SizeTy, /*IsVarArgs=*/false); 318755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 32629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCall return CGM.CreateRuntimeFunction(FTy, "__cxa_allocate_exception"); 33d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson} 34d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson 35629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCallstatic llvm::Constant *getFreeExceptionFn(CodeGenModule &CGM) { 3699533834ba8f3658559f334e68a518ebb6388ceaMike Stump // void __cxa_free_exception(void *thrown_exception); 378755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 382acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::FunctionType *FTy = 39629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCall llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*IsVarArgs=*/false); 408755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 41629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCall return CGM.CreateRuntimeFunction(FTy, "__cxa_free_exception"); 4299533834ba8f3658559f334e68a518ebb6388ceaMike Stump} 4399533834ba8f3658559f334e68a518ebb6388ceaMike Stump 44629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCallstatic llvm::Constant *getThrowFn(CodeGenModule &CGM) { 458755ec336108839b9621c3b18f0e175f8a3b671cMike Stump // void __cxa_throw(void *thrown_exception, std::type_info *tinfo, 4699533834ba8f3658559f334e68a518ebb6388ceaMike Stump // void (*dest) (void *)); 47d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson 48629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCall llvm::Type *Args[3] = { CGM.Int8PtrTy, CGM.Int8PtrTy, CGM.Int8PtrTy }; 492acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::FunctionType *FTy = 50629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCall llvm::FunctionType::get(CGM.VoidTy, Args, /*IsVarArgs=*/false); 518755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 52629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCall return CGM.CreateRuntimeFunction(FTy, "__cxa_throw"); 53d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson} 54d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson 55629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCallstatic llvm::Constant *getReThrowFn(CodeGenModule &CGM) { 5699533834ba8f3658559f334e68a518ebb6388ceaMike Stump // void __cxa_rethrow(); 57b4eea691866a3fa75722da9eba735c44f140398aMike Stump 582acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::FunctionType *FTy = 59629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCall llvm::FunctionType::get(CGM.VoidTy, /*IsVarArgs=*/false); 608755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 61629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCall return CGM.CreateRuntimeFunction(FTy, "__cxa_rethrow"); 62b4eea691866a3fa75722da9eba735c44f140398aMike Stump} 63b4eea691866a3fa75722da9eba735c44f140398aMike Stump 64629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCallstatic llvm::Constant *getGetExceptionPtrFn(CodeGenModule &CGM) { 65f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // void *__cxa_get_exception_ptr(void*); 66f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 672acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::FunctionType *FTy = 68629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCall llvm::FunctionType::get(CGM.Int8PtrTy, CGM.Int8PtrTy, /*IsVarArgs=*/false); 69f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 70629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCall return CGM.CreateRuntimeFunction(FTy, "__cxa_get_exception_ptr"); 71f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 72f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 73629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCallstatic llvm::Constant *getBeginCatchFn(CodeGenModule &CGM) { 74f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // void *__cxa_begin_catch(void*); 752bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 762acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::FunctionType *FTy = 77629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCall llvm::FunctionType::get(CGM.Int8PtrTy, CGM.Int8PtrTy, /*IsVarArgs=*/false); 788755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 79629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCall return CGM.CreateRuntimeFunction(FTy, "__cxa_begin_catch"); 802bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump} 812bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 82629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCallstatic llvm::Constant *getEndCatchFn(CodeGenModule &CGM) { 8399533834ba8f3658559f334e68a518ebb6388ceaMike Stump // void __cxa_end_catch(); 842bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 852acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::FunctionType *FTy = 86629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCall llvm::FunctionType::get(CGM.VoidTy, /*IsVarArgs=*/false); 878755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 88629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCall return CGM.CreateRuntimeFunction(FTy, "__cxa_end_catch"); 892bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump} 902bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 91629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCallstatic llvm::Constant *getUnexpectedFn(CodeGenModule &CGM) { 9214b0e4b4d55111e2b00db0072d20f4a8209fa5a4Richard Smith // void __cxa_call_unexpected(void *thrown_exception); 93cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump 942acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::FunctionType *FTy = 95629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCall llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*IsVarArgs=*/false); 968755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 97629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCall return CGM.CreateRuntimeFunction(FTy, "__cxa_call_unexpected"); 98cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump} 99cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump 100629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCallstatic llvm::Constant *getTerminateFn(CodeGenModule &CGM) { 10199533834ba8f3658559f334e68a518ebb6388ceaMike Stump // void __terminate(); 10299533834ba8f3658559f334e68a518ebb6388ceaMike Stump 1032acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::FunctionType *FTy = 104629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCall llvm::FunctionType::get(CGM.VoidTy, /*IsVarArgs=*/false); 1058755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 1065f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef name; 107256a76e0b0e0c9e65a3122917d553ef10bc84d29John McCall 108256a76e0b0e0c9e65a3122917d553ef10bc84d29John McCall // In C++, use std::terminate(). 109629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCall if (CGM.getLangOpts().CPlusPlus) 110256a76e0b0e0c9e65a3122917d553ef10bc84d29John McCall name = "_ZSt9terminatev"; // FIXME: mangling! 111629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCall else if (CGM.getLangOpts().ObjC1 && 112629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCall CGM.getLangOpts().ObjCRuntime.hasTerminate()) 113256a76e0b0e0c9e65a3122917d553ef10bc84d29John McCall name = "objc_terminate"; 114256a76e0b0e0c9e65a3122917d553ef10bc84d29John McCall else 115256a76e0b0e0c9e65a3122917d553ef10bc84d29John McCall name = "abort"; 116629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCall return CGM.CreateRuntimeFunction(FTy, name); 11779a9ad8e5eec3696989354be13a74a1106f64f72David Chisnall} 11879a9ad8e5eec3696989354be13a74a1106f64f72David Chisnall 119629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCallstatic llvm::Constant *getCatchallRethrowFn(CodeGenModule &CGM, 1205f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner StringRef Name) { 1212acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::FunctionType *FTy = 122629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCall llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*IsVarArgs=*/false); 1238262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCall 124629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCall return CGM.CreateRuntimeFunction(FTy, Name); 125f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 126f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 127af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramernamespace { 128af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer /// The exceptions personality for a function. 129af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer struct EHPersonality { 130af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer const char *PersonalityFn; 131af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer 132af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer // If this is non-null, this personality requires a non-standard 133af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer // function for rethrowing an exception after a catchall cleanup. 134af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer // This function must have prototype void(void*). 135af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer const char *CatchallRethrowFn; 136af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer 137af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer static const EHPersonality &get(const LangOptions &Lang); 138af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer static const EHPersonality GNU_C; 139af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer static const EHPersonality GNU_C_SJLJ; 140af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer static const EHPersonality GNU_ObjC; 14165bd4ac6ffbf6de30cd6f36735539ff8172a904aDavid Chisnall static const EHPersonality GNUstep_ObjC; 142af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer static const EHPersonality GNU_ObjCXX; 143af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer static const EHPersonality NeXT_ObjC; 144af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer static const EHPersonality GNU_CPlusPlus; 145af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer static const EHPersonality GNU_CPlusPlus_SJLJ; 146af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer }; 147af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer} 148af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer 1496bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesconst EHPersonality EHPersonality::GNU_C = { "__gcc_personality_v0", nullptr }; 150af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramerconst EHPersonality 1516bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen HinesEHPersonality::GNU_C_SJLJ = { "__gcc_personality_sj0", nullptr }; 1526bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesconst EHPersonality 1536bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen HinesEHPersonality::NeXT_ObjC = { "__objc_personality_v0", nullptr }; 1546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesconst EHPersonality 1556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen HinesEHPersonality::GNU_CPlusPlus = { "__gxx_personality_v0", nullptr }; 1566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hinesconst EHPersonality 1576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen HinesEHPersonality::GNU_CPlusPlus_SJLJ = { "__gxx_personality_sj0", nullptr }; 158af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramerconst EHPersonality 159af2771b147f1a5934c6c91574f1c2df986034e74Benjamin KramerEHPersonality::GNU_ObjC = {"__gnu_objc_personality_v0", "objc_exception_throw"}; 160af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramerconst EHPersonality 1616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen HinesEHPersonality::GNU_ObjCXX = { "__gnustep_objcxx_personality_v0", nullptr }; 16265bd4ac6ffbf6de30cd6f36735539ff8172a904aDavid Chisnallconst EHPersonality 1636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen HinesEHPersonality::GNUstep_ObjC = { "__gnustep_objc_personality_v0", nullptr }; 1648262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCall 1658262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCallstatic const EHPersonality &getCPersonality(const LangOptions &L) { 16644680786286f4f651603c6811f8412a3ee7fe975John McCall if (L.SjLjExceptions) 16744680786286f4f651603c6811f8412a3ee7fe975John McCall return EHPersonality::GNU_C_SJLJ; 1688262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCall return EHPersonality::GNU_C; 1698262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCall} 1708262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCall 1718262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCallstatic const EHPersonality &getObjCPersonality(const LangOptions &L) { 172260611a32535c851237926bfcf78869b13c07d5bJohn McCall switch (L.ObjCRuntime.getKind()) { 173260611a32535c851237926bfcf78869b13c07d5bJohn McCall case ObjCRuntime::FragileMacOSX: 174260611a32535c851237926bfcf78869b13c07d5bJohn McCall return getCPersonality(L); 175260611a32535c851237926bfcf78869b13c07d5bJohn McCall case ObjCRuntime::MacOSX: 176260611a32535c851237926bfcf78869b13c07d5bJohn McCall case ObjCRuntime::iOS: 177260611a32535c851237926bfcf78869b13c07d5bJohn McCall return EHPersonality::NeXT_ObjC; 17811d3f4cc27e6b923fc32481dc1bb5ec46c7d1f4bDavid Chisnall case ObjCRuntime::GNUstep: 17965bd4ac6ffbf6de30cd6f36735539ff8172a904aDavid Chisnall if (L.ObjCRuntime.getVersion() >= VersionTuple(1, 7)) 18065bd4ac6ffbf6de30cd6f36735539ff8172a904aDavid Chisnall return EHPersonality::GNUstep_ObjC; 18165bd4ac6ffbf6de30cd6f36735539ff8172a904aDavid Chisnall // fallthrough 18211d3f4cc27e6b923fc32481dc1bb5ec46c7d1f4bDavid Chisnall case ObjCRuntime::GCC: 183f7226fbe677a9c7578fa0613491ed15c6dc6a5e1John McCall case ObjCRuntime::ObjFW: 1848262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCall return EHPersonality::GNU_ObjC; 185f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 186260611a32535c851237926bfcf78869b13c07d5bJohn McCall llvm_unreachable("bad runtime kind"); 187f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 188f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1898262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCallstatic const EHPersonality &getCXXPersonality(const LangOptions &L) { 1908262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCall if (L.SjLjExceptions) 1918262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCall return EHPersonality::GNU_CPlusPlus_SJLJ; 192f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall else 1938262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCall return EHPersonality::GNU_CPlusPlus; 194f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 195f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 196f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// Determines the personality function to use when both C++ 197f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// and Objective-C exceptions are being caught. 1988262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCallstatic const EHPersonality &getObjCXXPersonality(const LangOptions &L) { 199260611a32535c851237926bfcf78869b13c07d5bJohn McCall switch (L.ObjCRuntime.getKind()) { 200f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // The ObjC personality defers to the C++ personality for non-ObjC 201f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // handlers. Unlike the C++ case, we use the same personality 202f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // function on targets using (backend-driven) SJLJ EH. 203260611a32535c851237926bfcf78869b13c07d5bJohn McCall case ObjCRuntime::MacOSX: 204260611a32535c851237926bfcf78869b13c07d5bJohn McCall case ObjCRuntime::iOS: 205260611a32535c851237926bfcf78869b13c07d5bJohn McCall return EHPersonality::NeXT_ObjC; 206260611a32535c851237926bfcf78869b13c07d5bJohn McCall 207260611a32535c851237926bfcf78869b13c07d5bJohn McCall // In the fragile ABI, just use C++ exception handling and hope 208260611a32535c851237926bfcf78869b13c07d5bJohn McCall // they're not doing crazy exception mixing. 209260611a32535c851237926bfcf78869b13c07d5bJohn McCall case ObjCRuntime::FragileMacOSX: 210260611a32535c851237926bfcf78869b13c07d5bJohn McCall return getCXXPersonality(L); 21179a9ad8e5eec3696989354be13a74a1106f64f72David Chisnall 21211d3f4cc27e6b923fc32481dc1bb5ec46c7d1f4bDavid Chisnall // The GCC runtime's personality function inherently doesn't support 2138262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCall // mixed EH. Use the C++ personality just to avoid returning null. 21411d3f4cc27e6b923fc32481dc1bb5ec46c7d1f4bDavid Chisnall case ObjCRuntime::GCC: 215f7226fbe677a9c7578fa0613491ed15c6dc6a5e1John McCall case ObjCRuntime::ObjFW: // XXX: this will change soon 21611d3f4cc27e6b923fc32481dc1bb5ec46c7d1f4bDavid Chisnall return EHPersonality::GNU_ObjC; 21711d3f4cc27e6b923fc32481dc1bb5ec46c7d1f4bDavid Chisnall case ObjCRuntime::GNUstep: 218260611a32535c851237926bfcf78869b13c07d5bJohn McCall return EHPersonality::GNU_ObjCXX; 219260611a32535c851237926bfcf78869b13c07d5bJohn McCall } 220260611a32535c851237926bfcf78869b13c07d5bJohn McCall llvm_unreachable("bad runtime kind"); 221f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 222f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 2238262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCallconst EHPersonality &EHPersonality::get(const LangOptions &L) { 2248262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCall if (L.CPlusPlus && L.ObjC1) 2258262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCall return getObjCXXPersonality(L); 2268262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCall else if (L.CPlusPlus) 2278262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCall return getCXXPersonality(L); 2288262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCall else if (L.ObjC1) 2298262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCall return getObjCPersonality(L); 230f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall else 2318262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCall return getCPersonality(L); 2328262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCall} 2338262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCall 234b25938303de0976b9f189363d43033e5788e3d36John McCallstatic llvm::Constant *getPersonalityFn(CodeGenModule &CGM, 2358262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCall const EHPersonality &Personality) { 2368262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCall llvm::Constant *Fn = 2378b418685e9e4f02f4eb2a76e1ec063e07552b68dChris Lattner CGM.CreateRuntimeFunction(llvm::FunctionType::get(CGM.Int32Ty, true), 238af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer Personality.PersonalityFn); 239b25938303de0976b9f189363d43033e5788e3d36John McCall return Fn; 240b25938303de0976b9f189363d43033e5788e3d36John McCall} 241b25938303de0976b9f189363d43033e5788e3d36John McCall 242b25938303de0976b9f189363d43033e5788e3d36John McCallstatic llvm::Constant *getOpaquePersonalityFn(CodeGenModule &CGM, 243b25938303de0976b9f189363d43033e5788e3d36John McCall const EHPersonality &Personality) { 244b25938303de0976b9f189363d43033e5788e3d36John McCall llvm::Constant *Fn = getPersonalityFn(CGM, Personality); 245d16c2cf1cafa413709aa487cbbd5dc392f1ba1ffJohn McCall return llvm::ConstantExpr::getBitCast(Fn, CGM.Int8PtrTy); 246b25938303de0976b9f189363d43033e5788e3d36John McCall} 247b25938303de0976b9f189363d43033e5788e3d36John McCall 248b25938303de0976b9f189363d43033e5788e3d36John McCall/// Check whether a personality function could reasonably be swapped 249b25938303de0976b9f189363d43033e5788e3d36John McCall/// for a C++ personality function. 250b25938303de0976b9f189363d43033e5788e3d36John McCallstatic bool PersonalityHasOnlyCXXUses(llvm::Constant *Fn) { 251651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (llvm::User *U : Fn->users()) { 252b25938303de0976b9f189363d43033e5788e3d36John McCall // Conditionally white-list bitcasts. 253651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (llvm::ConstantExpr *CE = dyn_cast<llvm::ConstantExpr>(U)) { 254b25938303de0976b9f189363d43033e5788e3d36John McCall if (CE->getOpcode() != llvm::Instruction::BitCast) return false; 255b25938303de0976b9f189363d43033e5788e3d36John McCall if (!PersonalityHasOnlyCXXUses(CE)) 256b25938303de0976b9f189363d43033e5788e3d36John McCall return false; 257b25938303de0976b9f189363d43033e5788e3d36John McCall continue; 258b25938303de0976b9f189363d43033e5788e3d36John McCall } 259b25938303de0976b9f189363d43033e5788e3d36John McCall 26040ccaccd21a4377cd76d6adda2b192dcf9514ef6Bill Wendling // Otherwise, it has to be a landingpad instruction. 261651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines llvm::LandingPadInst *LPI = dyn_cast<llvm::LandingPadInst>(U); 26240ccaccd21a4377cd76d6adda2b192dcf9514ef6Bill Wendling if (!LPI) return false; 263b25938303de0976b9f189363d43033e5788e3d36John McCall 26440ccaccd21a4377cd76d6adda2b192dcf9514ef6Bill Wendling for (unsigned I = 0, E = LPI->getNumClauses(); I != E; ++I) { 265b25938303de0976b9f189363d43033e5788e3d36John McCall // Look for something that would've been returned by the ObjC 266b25938303de0976b9f189363d43033e5788e3d36John McCall // runtime's GetEHType() method. 26740ccaccd21a4377cd76d6adda2b192dcf9514ef6Bill Wendling llvm::Value *Val = LPI->getClause(I)->stripPointerCasts(); 26840ccaccd21a4377cd76d6adda2b192dcf9514ef6Bill Wendling if (LPI->isCatch(I)) { 26940ccaccd21a4377cd76d6adda2b192dcf9514ef6Bill Wendling // Check if the catch value has the ObjC prefix. 270eecb6a1e8b95fcdb7d1a0d92b0a0311c041440cdBill Wendling if (llvm::GlobalVariable *GV = dyn_cast<llvm::GlobalVariable>(Val)) 271eecb6a1e8b95fcdb7d1a0d92b0a0311c041440cdBill Wendling // ObjC EH selector entries are always global variables with 272eecb6a1e8b95fcdb7d1a0d92b0a0311c041440cdBill Wendling // names starting like this. 273eecb6a1e8b95fcdb7d1a0d92b0a0311c041440cdBill Wendling if (GV->getName().startswith("OBJC_EHTYPE")) 274eecb6a1e8b95fcdb7d1a0d92b0a0311c041440cdBill Wendling return false; 27540ccaccd21a4377cd76d6adda2b192dcf9514ef6Bill Wendling } else { 27640ccaccd21a4377cd76d6adda2b192dcf9514ef6Bill Wendling // Check if any of the filter values have the ObjC prefix. 27740ccaccd21a4377cd76d6adda2b192dcf9514ef6Bill Wendling llvm::Constant *CVal = cast<llvm::Constant>(Val); 27840ccaccd21a4377cd76d6adda2b192dcf9514ef6Bill Wendling for (llvm::User::op_iterator 27940ccaccd21a4377cd76d6adda2b192dcf9514ef6Bill Wendling II = CVal->op_begin(), IE = CVal->op_end(); II != IE; ++II) { 280eecb6a1e8b95fcdb7d1a0d92b0a0311c041440cdBill Wendling if (llvm::GlobalVariable *GV = 281eecb6a1e8b95fcdb7d1a0d92b0a0311c041440cdBill Wendling cast<llvm::GlobalVariable>((*II)->stripPointerCasts())) 282eecb6a1e8b95fcdb7d1a0d92b0a0311c041440cdBill Wendling // ObjC EH selector entries are always global variables with 283eecb6a1e8b95fcdb7d1a0d92b0a0311c041440cdBill Wendling // names starting like this. 284eecb6a1e8b95fcdb7d1a0d92b0a0311c041440cdBill Wendling if (GV->getName().startswith("OBJC_EHTYPE")) 285eecb6a1e8b95fcdb7d1a0d92b0a0311c041440cdBill Wendling return false; 28640ccaccd21a4377cd76d6adda2b192dcf9514ef6Bill Wendling } 28740ccaccd21a4377cd76d6adda2b192dcf9514ef6Bill Wendling } 288b25938303de0976b9f189363d43033e5788e3d36John McCall } 289b25938303de0976b9f189363d43033e5788e3d36John McCall } 290b25938303de0976b9f189363d43033e5788e3d36John McCall 291b25938303de0976b9f189363d43033e5788e3d36John McCall return true; 292b25938303de0976b9f189363d43033e5788e3d36John McCall} 293b25938303de0976b9f189363d43033e5788e3d36John McCall 294b25938303de0976b9f189363d43033e5788e3d36John McCall/// Try to use the C++ personality function in ObjC++. Not doing this 295b25938303de0976b9f189363d43033e5788e3d36John McCall/// can cause some incompatibilities with gcc, which is more 296b25938303de0976b9f189363d43033e5788e3d36John McCall/// aggressive about only using the ObjC++ personality in a function 297b25938303de0976b9f189363d43033e5788e3d36John McCall/// when it really needs it. 298b25938303de0976b9f189363d43033e5788e3d36John McCallvoid CodeGenModule::SimplifyPersonality() { 299b25938303de0976b9f189363d43033e5788e3d36John McCall // If we're not in ObjC++ -fexceptions, there's nothing to do. 3004e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (!LangOpts.CPlusPlus || !LangOpts.ObjC1 || !LangOpts.Exceptions) 301b25938303de0976b9f189363d43033e5788e3d36John McCall return; 302b25938303de0976b9f189363d43033e5788e3d36John McCall 30370cd619e74306b1599d5579e6fd6a14bd9592281John McCall // Both the problem this endeavors to fix and the way the logic 30470cd619e74306b1599d5579e6fd6a14bd9592281John McCall // above works is specific to the NeXT runtime. 30570cd619e74306b1599d5579e6fd6a14bd9592281John McCall if (!LangOpts.ObjCRuntime.isNeXTFamily()) 30670cd619e74306b1599d5579e6fd6a14bd9592281John McCall return; 30770cd619e74306b1599d5579e6fd6a14bd9592281John McCall 3084e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie const EHPersonality &ObjCXX = EHPersonality::get(LangOpts); 3094e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie const EHPersonality &CXX = getCXXPersonality(LangOpts); 310af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer if (&ObjCXX == &CXX) 311b25938303de0976b9f189363d43033e5788e3d36John McCall return; 312b25938303de0976b9f189363d43033e5788e3d36John McCall 313af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer assert(std::strcmp(ObjCXX.PersonalityFn, CXX.PersonalityFn) != 0 && 314af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer "Different EHPersonalities using the same personality function."); 315af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer 316af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer llvm::Function *Fn = getModule().getFunction(ObjCXX.PersonalityFn); 317b25938303de0976b9f189363d43033e5788e3d36John McCall 318b25938303de0976b9f189363d43033e5788e3d36John McCall // Nothing to do if it's unused. 319b25938303de0976b9f189363d43033e5788e3d36John McCall if (!Fn || Fn->use_empty()) return; 320b25938303de0976b9f189363d43033e5788e3d36John McCall 321b25938303de0976b9f189363d43033e5788e3d36John McCall // Can't do the optimization if it has non-C++ uses. 322b25938303de0976b9f189363d43033e5788e3d36John McCall if (!PersonalityHasOnlyCXXUses(Fn)) return; 323b25938303de0976b9f189363d43033e5788e3d36John McCall 324b25938303de0976b9f189363d43033e5788e3d36John McCall // Create the C++ personality function and kill off the old 325b25938303de0976b9f189363d43033e5788e3d36John McCall // function. 326b25938303de0976b9f189363d43033e5788e3d36John McCall llvm::Constant *CXXFn = getPersonalityFn(*this, CXX); 327b25938303de0976b9f189363d43033e5788e3d36John McCall 328b25938303de0976b9f189363d43033e5788e3d36John McCall // This can happen if the user is screwing with us. 329b25938303de0976b9f189363d43033e5788e3d36John McCall if (Fn->getType() != CXXFn->getType()) return; 330b25938303de0976b9f189363d43033e5788e3d36John McCall 331b25938303de0976b9f189363d43033e5788e3d36John McCall Fn->replaceAllUsesWith(CXXFn); 332b25938303de0976b9f189363d43033e5788e3d36John McCall Fn->eraseFromParent(); 333f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 334f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 335f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// Returns the value to inject into a selector to indicate the 336f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// presence of a catch-all. 337f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallstatic llvm::Constant *getCatchAllValue(CodeGenFunction &CGF) { 338f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Possibly we should use @llvm.eh.catch.all.value here. 339d16c2cf1cafa413709aa487cbbd5dc392f1ba1ffJohn McCall return llvm::ConstantPointerNull::get(CGF.Int8PtrTy); 340f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 341f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 34209faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCallnamespace { 34309faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall /// A cleanup to free the exception object if its initialization 34409faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall /// throws. 345c4a1a8450a3613ef256a71b9d8305b41f79eef50John McCall struct FreeException : EHScopeStack::Cleanup { 346c4a1a8450a3613ef256a71b9d8305b41f79eef50John McCall llvm::Value *exn; 347c4a1a8450a3613ef256a71b9d8305b41f79eef50John McCall FreeException(llvm::Value *exn) : exn(exn) {} 348651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void Emit(CodeGenFunction &CGF, Flags flags) override { 349bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall CGF.EmitNounwindRuntimeCall(getFreeExceptionFn(CGF.CGM), exn); 35009faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall } 35109faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall }; 35209faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall} 35309faeabf39a6fab2e2beb6bf03da970c17d2049aJohn McCall 354ac418162692a951ca3796d6830496a85a2d12493John McCall// Emits an exception expression into the given location. This 355ac418162692a951ca3796d6830496a85a2d12493John McCall// differs from EmitAnyExprToMem only in that, if a final copy-ctor 356ac418162692a951ca3796d6830496a85a2d12493John McCall// call is required, an exception within that copy ctor causes 357ac418162692a951ca3796d6830496a85a2d12493John McCall// std::terminate to be invoked. 3583ad32c8d93eb65d1d4943d7df567fc9b4f55d137John McCallstatic void EmitAnyExprToExn(CodeGenFunction &CGF, const Expr *e, 3593ad32c8d93eb65d1d4943d7df567fc9b4f55d137John McCall llvm::Value *addr) { 360f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Make sure the exception object is cleaned up if there's an 361f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // exception during initialization. 3623ad32c8d93eb65d1d4943d7df567fc9b4f55d137John McCall CGF.pushFullExprCleanup<FreeException>(EHCleanup, addr); 3633ad32c8d93eb65d1d4943d7df567fc9b4f55d137John McCall EHScopeStack::stable_iterator cleanup = CGF.EHStack.stable_begin(); 364ac418162692a951ca3796d6830496a85a2d12493John McCall 365ac418162692a951ca3796d6830496a85a2d12493John McCall // __cxa_allocate_exception returns a void*; we need to cast this 366ac418162692a951ca3796d6830496a85a2d12493John McCall // to the appropriate type for the object. 3672acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::Type *ty = CGF.ConvertTypeForMem(e->getType())->getPointerTo(); 3683ad32c8d93eb65d1d4943d7df567fc9b4f55d137John McCall llvm::Value *typedAddr = CGF.Builder.CreateBitCast(addr, ty); 369ac418162692a951ca3796d6830496a85a2d12493John McCall 370ac418162692a951ca3796d6830496a85a2d12493John McCall // FIXME: this isn't quite right! If there's a final unelided call 371ac418162692a951ca3796d6830496a85a2d12493John McCall // to a copy constructor, then according to [except.terminate]p1 we 372ac418162692a951ca3796d6830496a85a2d12493John McCall // must call std::terminate() if that constructor throws, because 373ac418162692a951ca3796d6830496a85a2d12493John McCall // technically that copy occurs after the exception expression is 374ac418162692a951ca3796d6830496a85a2d12493John McCall // evaluated but before the exception is caught. But the best way 375ac418162692a951ca3796d6830496a85a2d12493John McCall // to handle that is to teach EmitAggExpr to do the final copy 376ac418162692a951ca3796d6830496a85a2d12493John McCall // differently if it can't be elided. 377649b4a1a9b5e6f768ca0cb84bd97b00f51083e15Chad Rosier CGF.EmitAnyExprToMem(e, typedAddr, e->getType().getQualifiers(), 378649b4a1a9b5e6f768ca0cb84bd97b00f51083e15Chad Rosier /*IsInit*/ true); 379ac418162692a951ca3796d6830496a85a2d12493John McCall 3803ad32c8d93eb65d1d4943d7df567fc9b4f55d137John McCall // Deactivate the cleanup block. 3816f103ba42cb69d50005a977c5ea583984ab63fc4John McCall CGF.DeactivateCleanupBlock(cleanup, cast<llvm::Instruction>(typedAddr)); 382f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 383f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 384f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallllvm::Value *CodeGenFunction::getExceptionSlot() { 38593c332a8ba2c193c435b293966d343dab15f555bJohn McCall if (!ExceptionSlot) 38693c332a8ba2c193c435b293966d343dab15f555bJohn McCall ExceptionSlot = CreateTempAlloca(Int8PtrTy, "exn.slot"); 387f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return ExceptionSlot; 3880f590be3808365e851352543faa6acbece50b686Mike Stump} 3890f590be3808365e851352543faa6acbece50b686Mike Stump 39093c332a8ba2c193c435b293966d343dab15f555bJohn McCallllvm::Value *CodeGenFunction::getEHSelectorSlot() { 39193c332a8ba2c193c435b293966d343dab15f555bJohn McCall if (!EHSelectorSlot) 39293c332a8ba2c193c435b293966d343dab15f555bJohn McCall EHSelectorSlot = CreateTempAlloca(Int32Ty, "ehselector.slot"); 39393c332a8ba2c193c435b293966d343dab15f555bJohn McCall return EHSelectorSlot; 39493c332a8ba2c193c435b293966d343dab15f555bJohn McCall} 39593c332a8ba2c193c435b293966d343dab15f555bJohn McCall 396ae270598d5c7a9a283d4b3ddce53b151c6e2b182Bill Wendlingllvm::Value *CodeGenFunction::getExceptionFromSlot() { 397ae270598d5c7a9a283d4b3ddce53b151c6e2b182Bill Wendling return Builder.CreateLoad(getExceptionSlot(), "exn"); 398ae270598d5c7a9a283d4b3ddce53b151c6e2b182Bill Wendling} 399ae270598d5c7a9a283d4b3ddce53b151c6e2b182Bill Wendling 400ae270598d5c7a9a283d4b3ddce53b151c6e2b182Bill Wendlingllvm::Value *CodeGenFunction::getSelectorFromSlot() { 401ae270598d5c7a9a283d4b3ddce53b151c6e2b182Bill Wendling return Builder.CreateLoad(getEHSelectorSlot(), "sel"); 402ae270598d5c7a9a283d4b3ddce53b151c6e2b182Bill Wendling} 403ae270598d5c7a9a283d4b3ddce53b151c6e2b182Bill Wendling 4044c71b8cded575b0cfc133c5da4502ca613982094Richard Smithvoid CodeGenFunction::EmitCXXThrowExpr(const CXXThrowExpr *E, 4054c71b8cded575b0cfc133c5da4502ca613982094Richard Smith bool KeepInsertionPoint) { 4066bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (CGM.getTarget().getTriple().isWindowsMSVCEnvironment()) { 4076bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ErrorUnsupported(E, "throw expression"); 4086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return; 4096bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 4106bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 411d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson if (!E->getSubExpr()) { 412bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall EmitNoreturnRuntimeCallOrInvoke(getReThrowFn(CGM), 413bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall ArrayRef<llvm::Value*>()); 4141eb2e59338c4b9c0429fc39ca98662adc9e7a3f2Douglas Gregor 415cd5b22e12b6513163dd131589746c194090f14e6John McCall // throw is an expression, and the expression emitters expect us 416cd5b22e12b6513163dd131589746c194090f14e6John McCall // to leave ourselves at a valid insertion point. 4174c71b8cded575b0cfc133c5da4502ca613982094Richard Smith if (KeepInsertionPoint) 4184c71b8cded575b0cfc133c5da4502ca613982094Richard Smith EmitBlock(createBasicBlock("throw.cont")); 419cd5b22e12b6513163dd131589746c194090f14e6John McCall 420d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson return; 421d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson } 4228755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 423d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson QualType ThrowType = E->getSubExpr()->getType(); 4248755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 4256a3c70ec59804347c99e96aa13934f63f4fed573Fariborz Jahanian if (ThrowType->isObjCObjectPointerType()) { 4266a3c70ec59804347c99e96aa13934f63f4fed573Fariborz Jahanian const Stmt *ThrowStmt = E->getSubExpr(); 4276a3c70ec59804347c99e96aa13934f63f4fed573Fariborz Jahanian const ObjCAtThrowStmt S(E->getExprLoc(), 4286a3c70ec59804347c99e96aa13934f63f4fed573Fariborz Jahanian const_cast<Stmt *>(ThrowStmt)); 4296a3c70ec59804347c99e96aa13934f63f4fed573Fariborz Jahanian CGM.getObjCRuntime().EmitThrowStmt(*this, S, false); 4306a3c70ec59804347c99e96aa13934f63f4fed573Fariborz Jahanian // This will clear insertion point which was not cleared in 4316a3c70ec59804347c99e96aa13934f63f4fed573Fariborz Jahanian // call to EmitThrowStmt. 4324c71b8cded575b0cfc133c5da4502ca613982094Richard Smith if (KeepInsertionPoint) 4334c71b8cded575b0cfc133c5da4502ca613982094Richard Smith EmitBlock(createBasicBlock("throw.cont")); 4346a3c70ec59804347c99e96aa13934f63f4fed573Fariborz Jahanian return; 4356a3c70ec59804347c99e96aa13934f63f4fed573Fariborz Jahanian } 4366a3c70ec59804347c99e96aa13934f63f4fed573Fariborz Jahanian 437d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson // Now allocate the exception object. 4382acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::Type *SizeTy = ConvertType(getContext().getSizeType()); 4393d3ec1c099ec8bfac3aa1fb0126fe515b7c7fa05John McCall uint64_t TypeSize = getContext().getTypeSizeInChars(ThrowType).getQuantity(); 4408755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 441629df0196eb305221d2c8aa9ab72293d05846f0bJohn McCall llvm::Constant *AllocExceptionFn = getAllocateExceptionFn(CGM); 442f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::CallInst *ExceptionPtr = 443bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall EmitNounwindRuntimeCall(AllocExceptionFn, 444bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall llvm::ConstantInt::get(SizeTy, TypeSize), 445bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall "exception"); 4468370c58b9295b32bee50443fe3ac43a47a2047e8Anders Carlsson 447ac418162692a951ca3796d6830496a85a2d12493John McCall EmitAnyExprToExn(*this, E->getSubExpr(), ExceptionPtr); 4488755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 449d3379292f90e1381d3236c68891bb725b02464b6Anders Carlsson // Now throw the exception. 45082a113adf8063baa70251dfa269d039ca22e2537Anders Carlsson llvm::Constant *TypeInfo = CGM.GetAddrOfRTTIDescriptor(ThrowType, 45182a113adf8063baa70251dfa269d039ca22e2537Anders Carlsson /*ForEH=*/true); 452ac418162692a951ca3796d6830496a85a2d12493John McCall 453ac418162692a951ca3796d6830496a85a2d12493John McCall // The address of the destructor. If the exception type has a 454ac418162692a951ca3796d6830496a85a2d12493John McCall // trivial destructor (or isn't a record), we just pass null. 4556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines llvm::Constant *Dtor = nullptr; 456ac418162692a951ca3796d6830496a85a2d12493John McCall if (const RecordType *RecordTy = ThrowType->getAs<RecordType>()) { 457ac418162692a951ca3796d6830496a85a2d12493John McCall CXXRecordDecl *Record = cast<CXXRecordDecl>(RecordTy->getDecl()); 458ac418162692a951ca3796d6830496a85a2d12493John McCall if (!Record->hasTrivialDestructor()) { 4591d110e05e0ff48c1c7a483d6b7fd094cdf28316aDouglas Gregor CXXDestructorDecl *DtorD = Record->getDestructor(); 460ac418162692a951ca3796d6830496a85a2d12493John McCall Dtor = CGM.GetAddrOfCXXDestructor(DtorD, Dtor_Complete); 461ac418162692a951ca3796d6830496a85a2d12493John McCall Dtor = llvm::ConstantExpr::getBitCast(Dtor, Int8PtrTy); 462ac418162692a951ca3796d6830496a85a2d12493John McCall } 463ac418162692a951ca3796d6830496a85a2d12493John McCall } 464ac418162692a951ca3796d6830496a85a2d12493John McCall if (!Dtor) Dtor = llvm::Constant::getNullValue(Int8PtrTy); 4658755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 466bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall llvm::Value *args[] = { ExceptionPtr, TypeInfo, Dtor }; 467bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall EmitNoreturnRuntimeCallOrInvoke(getThrowFn(CGM), args); 4688755ec336108839b9621c3b18f0e175f8a3b671cMike Stump 469cd5b22e12b6513163dd131589746c194090f14e6John McCall // throw is an expression, and the expression emitters expect us 470cd5b22e12b6513163dd131589746c194090f14e6John McCall // to leave ourselves at a valid insertion point. 4714c71b8cded575b0cfc133c5da4502ca613982094Richard Smith if (KeepInsertionPoint) 4724c71b8cded575b0cfc133c5da4502ca613982094Richard Smith EmitBlock(createBasicBlock("throw.cont")); 473756b5c4f9d52642d87d1948bee58f97a4f795b24Anders Carlsson} 4742bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 475cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stumpvoid CodeGenFunction::EmitStartEHSpec(const Decl *D) { 4764e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (!CGM.getLangOpts().CXXExceptions) 477a994ee4b197554282ae6b222c3284ccaa3a6484cAnders Carlsson return; 478a994ee4b197554282ae6b222c3284ccaa3a6484cAnders Carlsson 479cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D); 4806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (!FD) { 4816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // Check if CapturedDecl is nothrow and create terminate scope for it. 4826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (const CapturedDecl* CD = dyn_cast_or_null<CapturedDecl>(D)) { 4836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (CD->isNothrow()) 4846bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines EHStack.pushTerminate(); 4856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 486cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump return; 4876bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 488cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>(); 4896bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (!Proto) 490cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump return; 491cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump 492a968e97947b1281c3bb3c4d47a952b3801d9bb02Sebastian Redl ExceptionSpecificationType EST = Proto->getExceptionSpecType(); 493a968e97947b1281c3bb3c4d47a952b3801d9bb02Sebastian Redl if (isNoexceptExceptionSpec(EST)) { 494a968e97947b1281c3bb3c4d47a952b3801d9bb02Sebastian Redl if (Proto->getNoexceptSpec(getContext()) == FunctionProtoType::NR_Nothrow) { 495a968e97947b1281c3bb3c4d47a952b3801d9bb02Sebastian Redl // noexcept functions are simple terminate scopes. 496a968e97947b1281c3bb3c4d47a952b3801d9bb02Sebastian Redl EHStack.pushTerminate(); 497a968e97947b1281c3bb3c4d47a952b3801d9bb02Sebastian Redl } 498a968e97947b1281c3bb3c4d47a952b3801d9bb02Sebastian Redl } else if (EST == EST_Dynamic || EST == EST_DynamicNone) { 499a968e97947b1281c3bb3c4d47a952b3801d9bb02Sebastian Redl unsigned NumExceptions = Proto->getNumExceptions(); 500a968e97947b1281c3bb3c4d47a952b3801d9bb02Sebastian Redl EHFilterScope *Filter = EHStack.pushFilter(NumExceptions); 501a968e97947b1281c3bb3c4d47a952b3801d9bb02Sebastian Redl 502a968e97947b1281c3bb3c4d47a952b3801d9bb02Sebastian Redl for (unsigned I = 0; I != NumExceptions; ++I) { 503a968e97947b1281c3bb3c4d47a952b3801d9bb02Sebastian Redl QualType Ty = Proto->getExceptionType(I); 504a968e97947b1281c3bb3c4d47a952b3801d9bb02Sebastian Redl QualType ExceptType = Ty.getNonReferenceType().getUnqualifiedType(); 505a968e97947b1281c3bb3c4d47a952b3801d9bb02Sebastian Redl llvm::Value *EHType = CGM.GetAddrOfRTTIDescriptor(ExceptType, 506a968e97947b1281c3bb3c4d47a952b3801d9bb02Sebastian Redl /*ForEH=*/true); 507a968e97947b1281c3bb3c4d47a952b3801d9bb02Sebastian Redl Filter->setFilter(I, EHType); 508a968e97947b1281c3bb3c4d47a952b3801d9bb02Sebastian Redl } 509cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump } 510cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump} 511cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump 512777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall/// Emit the dispatch block for a filter scope if necessary. 513777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCallstatic void emitFilterDispatchBlock(CodeGenFunction &CGF, 514777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall EHFilterScope &filterScope) { 515777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall llvm::BasicBlock *dispatchBlock = filterScope.getCachedEHDispatchBlock(); 516777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall if (!dispatchBlock) return; 517777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall if (dispatchBlock->use_empty()) { 518777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall delete dispatchBlock; 519777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall return; 520777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall } 521777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 522777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall CGF.EmitBlockAfterUses(dispatchBlock); 523777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 524777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // If this isn't a catch-all filter, we need to check whether we got 525777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // here because the filter triggered. 526777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall if (filterScope.getNumFilters()) { 527777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // Load the selector value. 528ae270598d5c7a9a283d4b3ddce53b151c6e2b182Bill Wendling llvm::Value *selector = CGF.getSelectorFromSlot(); 529777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall llvm::BasicBlock *unexpectedBB = CGF.createBasicBlock("ehspec.unexpected"); 530777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 531777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall llvm::Value *zero = CGF.Builder.getInt32(0); 532777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall llvm::Value *failsFilter = 533777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall CGF.Builder.CreateICmpSLT(selector, zero, "ehspec.fails"); 534c686004145b1f4dbeb38173a0886ba7040ae0089David Chisnall CGF.Builder.CreateCondBr(failsFilter, unexpectedBB, CGF.getEHResumeBlock(false)); 535777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 536777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall CGF.EmitBlock(unexpectedBB); 537777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall } 538777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 539777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // Call __cxa_call_unexpected. This doesn't need to be an invoke 540777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // because __cxa_call_unexpected magically filters exceptions 541777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // according to the last landing pad the exception was thrown 542777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // into. Seriously. 543ae270598d5c7a9a283d4b3ddce53b151c6e2b182Bill Wendling llvm::Value *exn = CGF.getExceptionFromSlot(); 544bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall CGF.EmitRuntimeCall(getUnexpectedFn(CGF.CGM), exn) 545777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall ->setDoesNotReturn(); 546777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall CGF.Builder.CreateUnreachable(); 547777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall} 548777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 549cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stumpvoid CodeGenFunction::EmitEndEHSpec(const Decl *D) { 5504e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (!CGM.getLangOpts().CXXExceptions) 551a994ee4b197554282ae6b222c3284ccaa3a6484cAnders Carlsson return; 552a994ee4b197554282ae6b222c3284ccaa3a6484cAnders Carlsson 553cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump const FunctionDecl* FD = dyn_cast_or_null<FunctionDecl>(D); 5546bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (!FD) { 5556bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines // Check if CapturedDecl is nothrow and pop terminate scope for it. 5566bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (const CapturedDecl* CD = dyn_cast_or_null<CapturedDecl>(D)) { 5576bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (CD->isNothrow()) 5586bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines EHStack.popTerminate(); 5596bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 560cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump return; 5616bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 562cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump const FunctionProtoType *Proto = FD->getType()->getAs<FunctionProtoType>(); 5636bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (!Proto) 564cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump return; 565cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump 566a968e97947b1281c3bb3c4d47a952b3801d9bb02Sebastian Redl ExceptionSpecificationType EST = Proto->getExceptionSpecType(); 567a968e97947b1281c3bb3c4d47a952b3801d9bb02Sebastian Redl if (isNoexceptExceptionSpec(EST)) { 568a968e97947b1281c3bb3c4d47a952b3801d9bb02Sebastian Redl if (Proto->getNoexceptSpec(getContext()) == FunctionProtoType::NR_Nothrow) { 569a968e97947b1281c3bb3c4d47a952b3801d9bb02Sebastian Redl EHStack.popTerminate(); 570a968e97947b1281c3bb3c4d47a952b3801d9bb02Sebastian Redl } 571a968e97947b1281c3bb3c4d47a952b3801d9bb02Sebastian Redl } else if (EST == EST_Dynamic || EST == EST_DynamicNone) { 572777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall EHFilterScope &filterScope = cast<EHFilterScope>(*EHStack.begin()); 573777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall emitFilterDispatchBlock(*this, filterScope); 574a968e97947b1281c3bb3c4d47a952b3801d9bb02Sebastian Redl EHStack.popFilter(); 575a968e97947b1281c3bb3c4d47a952b3801d9bb02Sebastian Redl } 576cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump} 577cce3d4f9812182ed4e551b7cf0fc86576be8d9c5Mike Stump 5782bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stumpvoid CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) { 5796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (CGM.getTarget().getTriple().isWindowsMSVCEnvironment()) { 5806bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines ErrorUnsupported(&S, "try statement"); 5816bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return; 5826bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines } 5836bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines 58459a7000a79118e4c140885ccbb2ac6a686a73092John McCall EnterCXXTryStmt(S); 5859fc6a7774643a810c8501dae2323e863fefb623eJohn McCall EmitStmt(S.getTryBlock()); 58659a7000a79118e4c140885ccbb2ac6a686a73092John McCall ExitCXXTryStmt(S); 5879fc6a7774643a810c8501dae2323e863fefb623eJohn McCall} 5889fc6a7774643a810c8501dae2323e863fefb623eJohn McCall 58959a7000a79118e4c140885ccbb2ac6a686a73092John McCallvoid CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) { 590f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall unsigned NumHandlers = S.getNumHandlers(); 591f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHCatchScope *CatchScope = EHStack.pushCatch(NumHandlers); 592f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 593f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall for (unsigned I = 0; I != NumHandlers; ++I) { 594f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall const CXXCatchStmt *C = S.getHandler(I); 595f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 596f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::BasicBlock *Handler = createBasicBlock("catch"); 597f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (C->getExceptionDecl()) { 598f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // FIXME: Dropping the reference type on the type into makes it 599f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // impossible to correctly implement catch-by-reference 600f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // semantics for pointers. Unfortunately, this is what all 601f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // existing compilers do, and it's not clear that the standard 602f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // personality routine is capable of doing this right. See C++ DR 388: 603f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#388 604f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall QualType CaughtType = C->getCaughtType(); 605f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CaughtType = CaughtType.getNonReferenceType().getUnqualifiedType(); 6065a180397870944548aaadeaebf58e415885b9489John McCall 607ef8225444452a1486bd721f3285301fe84643b00Stephen Hines llvm::Constant *TypeInfo = nullptr; 6085a180397870944548aaadeaebf58e415885b9489John McCall if (CaughtType->isObjCObjectPointerType()) 609cf5abc7ba032bd35158e4d75b0bc92a482fc67e8Fariborz Jahanian TypeInfo = CGM.getObjCRuntime().GetEHType(CaughtType); 6105a180397870944548aaadeaebf58e415885b9489John McCall else 61182a113adf8063baa70251dfa269d039ca22e2537Anders Carlsson TypeInfo = CGM.GetAddrOfRTTIDescriptor(CaughtType, /*ForEH=*/true); 612f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CatchScope->setHandler(I, TypeInfo, Handler); 613f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } else { 614f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // No exception decl indicates '...', a catch-all. 615f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CatchScope->setCatchAllHandler(I, Handler); 616f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 617f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 618f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 619f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 620777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCallllvm::BasicBlock * 621777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCallCodeGenFunction::getEHDispatchBlock(EHScopeStack::stable_iterator si) { 622777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // The dispatch block for the end of the scope chain is a block that 623777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // just resumes unwinding. 624777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall if (si == EHStack.stable_end()) 625c686004145b1f4dbeb38173a0886ba7040ae0089David Chisnall return getEHResumeBlock(true); 626777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 627777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // Otherwise, we should look at the actual scope. 628777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall EHScope &scope = *EHStack.find(si); 629777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 630777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall llvm::BasicBlock *dispatchBlock = scope.getCachedEHDispatchBlock(); 631777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall if (!dispatchBlock) { 632777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall switch (scope.getKind()) { 633777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall case EHScope::Catch: { 634777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // Apply a special case to a single catch-all. 635777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall EHCatchScope &catchScope = cast<EHCatchScope>(scope); 636777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall if (catchScope.getNumHandlers() == 1 && 637777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall catchScope.getHandler(0).isCatchAll()) { 638777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall dispatchBlock = catchScope.getHandler(0).Block; 639777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 640777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // Otherwise, make a dispatch block. 641777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall } else { 642777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall dispatchBlock = createBasicBlock("catch.dispatch"); 643777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall } 644777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall break; 645777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall } 646777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 647777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall case EHScope::Cleanup: 648777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall dispatchBlock = createBasicBlock("ehcleanup"); 649777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall break; 650777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 651777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall case EHScope::Filter: 652777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall dispatchBlock = createBasicBlock("filter.dispatch"); 653777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall break; 654777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 655777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall case EHScope::Terminate: 656777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall dispatchBlock = getTerminateHandler(); 657777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall break; 658777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall } 659777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall scope.setCachedEHDispatchBlock(dispatchBlock); 660777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall } 661777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall return dispatchBlock; 662777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall} 663777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 664f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// Check whether this is a non-EH scope, i.e. a scope which doesn't 665f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// affect exception handling. Currently, the only non-EH scopes are 666f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// normal-only cleanup scopes. 667f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallstatic bool isNonEHScope(const EHScope &S) { 668da65ea86482bc116906edfb9ba1d7124f76cc867John McCall switch (S.getKind()) { 6691f0fca54676cfa8616e7f3cd7a26788ab937e3cdJohn McCall case EHScope::Cleanup: 6701f0fca54676cfa8616e7f3cd7a26788ab937e3cdJohn McCall return !cast<EHCleanupScope>(S).isEHCleanup(); 671da65ea86482bc116906edfb9ba1d7124f76cc867John McCall case EHScope::Filter: 672da65ea86482bc116906edfb9ba1d7124f76cc867John McCall case EHScope::Catch: 673da65ea86482bc116906edfb9ba1d7124f76cc867John McCall case EHScope::Terminate: 674da65ea86482bc116906edfb9ba1d7124f76cc867John McCall return false; 675da65ea86482bc116906edfb9ba1d7124f76cc867John McCall } 676da65ea86482bc116906edfb9ba1d7124f76cc867John McCall 6773026348bd4c13a0f83b59839f64065e0fcbea253David Blaikie llvm_unreachable("Invalid EHScope Kind!"); 678f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 6799fc6a7774643a810c8501dae2323e863fefb623eJohn McCall 680f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallllvm::BasicBlock *CodeGenFunction::getInvokeDestImpl() { 681f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(EHStack.requiresLandingPad()); 682f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(!EHStack.empty()); 6839fc6a7774643a810c8501dae2323e863fefb623eJohn McCall 6844e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie if (!CGM.getLangOpts().Exceptions) 6856bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines return nullptr; 686da65ea86482bc116906edfb9ba1d7124f76cc867John McCall 687f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Check the innermost scope for a cached landing pad. If this is 688f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // a non-EH cleanup, we'll check enclosing scopes in EmitLandingPad. 689f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::BasicBlock *LP = EHStack.begin()->getCachedLandingPad(); 690f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (LP) return LP; 691f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 692f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Build the landing pad for this scope. 693f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall LP = EmitLandingPad(); 694f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(LP); 695f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 696f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Cache the landing pad on the innermost scope. If this is a 697f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // non-EH scope, cache the landing pad on the enclosing scope, too. 698f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall for (EHScopeStack::iterator ir = EHStack.begin(); true; ++ir) { 699f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall ir->setCachedLandingPad(LP); 700f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (!isNonEHScope(*ir)) break; 701f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 702f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 703f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return LP; 7049fc6a7774643a810c8501dae2323e863fefb623eJohn McCall} 7059fc6a7774643a810c8501dae2323e863fefb623eJohn McCall 706f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallllvm::BasicBlock *CodeGenFunction::EmitLandingPad() { 707f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(EHStack.requiresLandingPad()); 708f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 709777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall EHScope &innermostEHScope = *EHStack.find(EHStack.getInnermostEHScope()); 710777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall switch (innermostEHScope.getKind()) { 711777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall case EHScope::Terminate: 712777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall return getTerminateLandingPad(); 713f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 714777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall case EHScope::Catch: 715777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall case EHScope::Cleanup: 716777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall case EHScope::Filter: 717777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall if (llvm::BasicBlock *lpad = innermostEHScope.getCachedLandingPad()) 718777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall return lpad; 719f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 720f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 721f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Save the current IR generation state. 722777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall CGBuilderTy::InsertPoint savedIP = Builder.saveAndClearIP(); 723651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines SaveAndRestoreLocation AutoRestoreLocation(*this, Builder); 724651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines if (CGDebugInfo *DI = getDebugInfo()) 72559f0a5a5481a6dcfafd092dd944e6cfb7d146d4cAdrian Prantl DI->EmitLocation(Builder, CurEHLocation); 726f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 7274e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie const EHPersonality &personality = EHPersonality::get(getLangOpts()); 7288262b6a44c98cf14e1d5f347a01e6bf44858198fJohn McCall 729f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Create and configure the landing pad. 730777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall llvm::BasicBlock *lpad = createBasicBlock("lpad"); 731777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall EmitBlock(lpad); 732f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 733285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling llvm::LandingPadInst *LPadInst = 734285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling Builder.CreateLandingPad(llvm::StructType::get(Int8PtrTy, Int32Ty, NULL), 735285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling getOpaquePersonalityFn(CGM, personality), 0); 736285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling 737285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling llvm::Value *LPadExn = Builder.CreateExtractValue(LPadInst, 0); 738285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling Builder.CreateStore(LPadExn, getExceptionSlot()); 739285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling llvm::Value *LPadSel = Builder.CreateExtractValue(LPadInst, 1); 740285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling Builder.CreateStore(LPadSel, getEHSelectorSlot()); 741285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling 742f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Save the exception pointer. It's safe to use a single exception 743f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // pointer per function because EH cleanups can never have nested 744f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // try/catches. 745285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling // Build the landingpad instruction. 746f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 747f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Accumulate all the handlers in scope. 748777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall bool hasCatchAll = false; 749777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall bool hasCleanup = false; 750777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall bool hasFilter = false; 751777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall SmallVector<llvm::Value*, 4> filterTypes; 752777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall llvm::SmallPtrSet<llvm::Value*, 4> catchTypes; 753f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall for (EHScopeStack::iterator I = EHStack.begin(), E = EHStack.end(); 754f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall I != E; ++I) { 755f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 756f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall switch (I->getKind()) { 7571f0fca54676cfa8616e7f3cd7a26788ab937e3cdJohn McCall case EHScope::Cleanup: 758777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // If we have a cleanup, remember that. 759777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall hasCleanup = (hasCleanup || cast<EHCleanupScope>(*I).isEHCleanup()); 760da65ea86482bc116906edfb9ba1d7124f76cc867John McCall continue; 761da65ea86482bc116906edfb9ba1d7124f76cc867John McCall 762f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall case EHScope::Filter: { 763f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(I.next() == EHStack.end() && "EH filter is not end of EH stack"); 764777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall assert(!hasCatchAll && "EH filter reached after catch-all"); 765f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 766285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling // Filter scopes get added to the landingpad in weird ways. 767777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall EHFilterScope &filter = cast<EHFilterScope>(*I); 768777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall hasFilter = true; 769f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 7708990daf237a48fa2eed3d0546687fc097a004db6Bill Wendling // Add all the filter values. 7718990daf237a48fa2eed3d0546687fc097a004db6Bill Wendling for (unsigned i = 0, e = filter.getNumFilters(); i != e; ++i) 7728990daf237a48fa2eed3d0546687fc097a004db6Bill Wendling filterTypes.push_back(filter.getFilter(i)); 773f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall goto done; 774f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 775f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 776f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall case EHScope::Terminate: 777f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Terminate scopes are basically catch-alls. 778777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall assert(!hasCatchAll); 779777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall hasCatchAll = true; 780f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall goto done; 781f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 782f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall case EHScope::Catch: 783f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall break; 784f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 785f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 786777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall EHCatchScope &catchScope = cast<EHCatchScope>(*I); 787777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall for (unsigned hi = 0, he = catchScope.getNumHandlers(); hi != he; ++hi) { 788777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall EHCatchScope::Handler handler = catchScope.getHandler(hi); 789777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 790777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // If this is a catch-all, register that and abort. 791777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall if (!handler.Type) { 792777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall assert(!hasCatchAll); 793777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall hasCatchAll = true; 794777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall goto done; 795f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 796f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 797f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Check whether we already have a handler for this type. 798285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling if (catchTypes.insert(handler.Type)) 799285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling // If not, add it directly to the landingpad. 800285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling LPadInst->addClause(handler.Type); 8012bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump } 8022bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump } 8032bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 804f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall done: 805285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling // If we have a catch-all, add null to the landingpad. 806777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall assert(!(hasCatchAll && hasFilter)); 807777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall if (hasCatchAll) { 808285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling LPadInst->addClause(getCatchAllValue(*this)); 809f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 810f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // If we have an EH filter, we need to add those handlers in the 811285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling // right place in the landingpad, which is to say, at the end. 812777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall } else if (hasFilter) { 81340ccaccd21a4377cd76d6adda2b192dcf9514ef6Bill Wendling // Create a filter expression: a constant array indicating which filter 81440ccaccd21a4377cd76d6adda2b192dcf9514ef6Bill Wendling // types there are. The personality routine only lands here if the filter 81540ccaccd21a4377cd76d6adda2b192dcf9514ef6Bill Wendling // doesn't match. 816cfa88f893915ceb8ae4ce2f17c46c24a4d67502fDmitri Gribenko SmallVector<llvm::Constant*, 8> Filters; 817285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling llvm::ArrayType *AType = 818285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling llvm::ArrayType::get(!filterTypes.empty() ? 819285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling filterTypes[0]->getType() : Int8PtrTy, 820285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling filterTypes.size()); 821285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling 822285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling for (unsigned i = 0, e = filterTypes.size(); i != e; ++i) 823285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling Filters.push_back(cast<llvm::Constant>(filterTypes[i])); 824285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling llvm::Constant *FilterArray = llvm::ConstantArray::get(AType, Filters); 825285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling LPadInst->addClause(FilterArray); 826f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 827f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Also check whether we need a cleanup. 828285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling if (hasCleanup) 829285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling LPadInst->setCleanup(true); 830f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 831f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Otherwise, signal that we at least have cleanups. 832ef8225444452a1486bd721f3285301fe84643b00Stephen Hines } else if (hasCleanup) { 833ef8225444452a1486bd721f3285301fe84643b00Stephen Hines LPadInst->setCleanup(true); 8340f590be3808365e851352543faa6acbece50b686Mike Stump } 8352bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 836285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling assert((LPadInst->getNumClauses() > 0 || LPadInst->isCleanup()) && 837285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling "landingpad instruction has no clauses!"); 838f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 839f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Tell the backend how to generate the landing pad. 840777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall Builder.CreateBr(getEHDispatchBlock(EHStack.getInnermostEHScope())); 841f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 842f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Restore the old IR generation state. 843777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall Builder.restoreIP(savedIP); 844f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 845777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall return lpad; 846f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 8470f590be3808365e851352543faa6acbece50b686Mike Stump 8488e3f86193995c47ee0d229e4336c3382410f09f5John McCallnamespace { 8498e3f86193995c47ee0d229e4336c3382410f09f5John McCall /// A cleanup to call __cxa_end_catch. In many cases, the caught 8508e3f86193995c47ee0d229e4336c3382410f09f5John McCall /// exception type lets us state definitively that the thrown exception 8518e3f86193995c47ee0d229e4336c3382410f09f5John McCall /// type does not have a destructor. In particular: 8528e3f86193995c47ee0d229e4336c3382410f09f5John McCall /// - Catch-alls tell us nothing, so we have to conservatively 8538e3f86193995c47ee0d229e4336c3382410f09f5John McCall /// assume that the thrown exception might have a destructor. 8548e3f86193995c47ee0d229e4336c3382410f09f5John McCall /// - Catches by reference behave according to their base types. 8558e3f86193995c47ee0d229e4336c3382410f09f5John McCall /// - Catches of non-record types will only trigger for exceptions 8568e3f86193995c47ee0d229e4336c3382410f09f5John McCall /// of non-record types, which never have destructors. 8578e3f86193995c47ee0d229e4336c3382410f09f5John McCall /// - Catches of record types can trigger for arbitrary subclasses 8588e3f86193995c47ee0d229e4336c3382410f09f5John McCall /// of the caught type, so we have to assume the actual thrown 8598e3f86193995c47ee0d229e4336c3382410f09f5John McCall /// exception type might have a throwing destructor, even if the 8608e3f86193995c47ee0d229e4336c3382410f09f5John McCall /// caught type's destructor is trivial or nothrow. 8611f0fca54676cfa8616e7f3cd7a26788ab937e3cdJohn McCall struct CallEndCatch : EHScopeStack::Cleanup { 8628e3f86193995c47ee0d229e4336c3382410f09f5John McCall CallEndCatch(bool MightThrow) : MightThrow(MightThrow) {} 8638e3f86193995c47ee0d229e4336c3382410f09f5John McCall bool MightThrow; 8648e3f86193995c47ee0d229e4336c3382410f09f5John McCall 865651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void Emit(CodeGenFunction &CGF, Flags flags) override { 8668e3f86193995c47ee0d229e4336c3382410f09f5John McCall if (!MightThrow) { 867bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall CGF.EmitNounwindRuntimeCall(getEndCatchFn(CGF.CGM)); 8688e3f86193995c47ee0d229e4336c3382410f09f5John McCall return; 8698e3f86193995c47ee0d229e4336c3382410f09f5John McCall } 8708e3f86193995c47ee0d229e4336c3382410f09f5John McCall 871bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall CGF.EmitRuntimeCallOrInvoke(getEndCatchFn(CGF.CGM)); 8728e3f86193995c47ee0d229e4336c3382410f09f5John McCall } 8738e3f86193995c47ee0d229e4336c3382410f09f5John McCall }; 8748e3f86193995c47ee0d229e4336c3382410f09f5John McCall} 8758e3f86193995c47ee0d229e4336c3382410f09f5John McCall 876f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// Emits a call to __cxa_begin_catch and enters a cleanup to call 877f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// __cxa_end_catch. 8788e3f86193995c47ee0d229e4336c3382410f09f5John McCall/// 8798e3f86193995c47ee0d229e4336c3382410f09f5John McCall/// \param EndMightThrow - true if __cxa_end_catch might throw 8808e3f86193995c47ee0d229e4336c3382410f09f5John McCallstatic llvm::Value *CallBeginCatch(CodeGenFunction &CGF, 8818e3f86193995c47ee0d229e4336c3382410f09f5John McCall llvm::Value *Exn, 8828e3f86193995c47ee0d229e4336c3382410f09f5John McCall bool EndMightThrow) { 883bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall llvm::CallInst *call = 884bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall CGF.EmitNounwindRuntimeCall(getBeginCatchFn(CGF.CGM), Exn); 8850f590be3808365e851352543faa6acbece50b686Mike Stump 8861f0fca54676cfa8616e7f3cd7a26788ab937e3cdJohn McCall CGF.EHStack.pushCleanup<CallEndCatch>(NormalAndEHCleanup, EndMightThrow); 887f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 888bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall return call; 889f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 890f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 891f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// A "special initializer" callback for initializing a catch 892f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// parameter during catch initialization. 893f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallstatic void InitCatchParam(CodeGenFunction &CGF, 894f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall const VarDecl &CatchParam, 8954ee7dc2369c1f0257a73b2e83a7d38fdebdd9176Nick Lewycky llvm::Value *ParamAddr, 8964ee7dc2369c1f0257a73b2e83a7d38fdebdd9176Nick Lewycky SourceLocation Loc) { 897f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Load the exception from where the landing pad saved it. 898ae270598d5c7a9a283d4b3ddce53b151c6e2b182Bill Wendling llvm::Value *Exn = CGF.getExceptionFromSlot(); 899f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 900f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CanQualType CatchType = 901f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.CGM.getContext().getCanonicalType(CatchParam.getType()); 9022acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::Type *LLVMCatchTy = CGF.ConvertTypeForMem(CatchType); 903f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 904f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // If we're catching by reference, we can just cast the object 905f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // pointer to the appropriate pointer. 906f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (isa<ReferenceType>(CatchType)) { 907204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall QualType CaughtType = cast<ReferenceType>(CatchType)->getPointeeType(); 908204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall bool EndCatchMightThrow = CaughtType->isRecordType(); 9098e3f86193995c47ee0d229e4336c3382410f09f5John McCall 910f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // __cxa_begin_catch returns the adjusted object pointer. 9118e3f86193995c47ee0d229e4336c3382410f09f5John McCall llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, EndCatchMightThrow); 912204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall 913204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall // We have no way to tell the personality function that we're 914204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall // catching by reference, so if we're catching a pointer, 915204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall // __cxa_begin_catch will actually return that pointer by value. 916204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall if (const PointerType *PT = dyn_cast<PointerType>(CaughtType)) { 917204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall QualType PointeeType = PT->getPointeeType(); 918204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall 919204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall // When catching by reference, generally we should just ignore 920204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall // this by-value pointer and use the exception object instead. 921204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall if (!PointeeType->isRecordType()) { 922204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall 923204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall // Exn points to the struct _Unwind_Exception header, which 924204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall // we have to skip past in order to reach the exception data. 925204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall unsigned HeaderSize = 926204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall CGF.CGM.getTargetCodeGenInfo().getSizeOfUnwindException(); 927204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall AdjustedExn = CGF.Builder.CreateConstGEP1_32(Exn, HeaderSize); 928204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall 929204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall // However, if we're catching a pointer-to-record type that won't 930204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall // work, because the personality function might have adjusted 931204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall // the pointer. There's actually no way for us to fully satisfy 932204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall // the language/ABI contract here: we can't use Exn because it 933204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall // might have the wrong adjustment, but we can't use the by-value 934204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall // pointer because it's off by a level of abstraction. 935204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall // 936204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall // The current solution is to dump the adjusted pointer into an 937204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall // alloca, which breaks language semantics (because changing the 938204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall // pointer doesn't change the exception) but at least works. 939204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall // The better solution would be to filter out non-exact matches 940204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall // and rethrow them, but this is tricky because the rethrow 941204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall // really needs to be catchable by other sites at this landing 942204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall // pad. The best solution is to fix the personality function. 943204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall } else { 944204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall // Pull the pointer for the reference type off. 9452acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::Type *PtrTy = 946204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall cast<llvm::PointerType>(LLVMCatchTy)->getElementType(); 947204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall 948204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall // Create the temporary and write the adjusted pointer into it. 949204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall llvm::Value *ExnPtrTmp = CGF.CreateTempAlloca(PtrTy, "exn.byref.tmp"); 950204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall llvm::Value *Casted = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy); 951204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall CGF.Builder.CreateStore(Casted, ExnPtrTmp); 952204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall 953204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall // Bind the reference to the temporary. 954204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall AdjustedExn = ExnPtrTmp; 955204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall } 956204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall } 957204b075fcc47c3f2aa7276dfba9b42eb25840b53John McCall 958f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *ExnCast = 959f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.byref"); 960f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.Builder.CreateStore(ExnCast, ParamAddr); 961f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return; 962a086783570f76062a345e761811296dc8df571c8Mike Stump } 9632bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 9649d232c884ea9872d6555df0fd7359699819bc1f1John McCall // Scalars and complexes. 9659d232c884ea9872d6555df0fd7359699819bc1f1John McCall TypeEvaluationKind TEK = CGF.getEvaluationKind(CatchType); 9669d232c884ea9872d6555df0fd7359699819bc1f1John McCall if (TEK != TEK_Aggregate) { 9678e3f86193995c47ee0d229e4336c3382410f09f5John McCall llvm::Value *AdjustedExn = CallBeginCatch(CGF, Exn, false); 968f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 969f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // If the catch type is a pointer type, __cxa_begin_catch returns 970f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // the pointer by value. 971f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (CatchType->hasPointerRepresentation()) { 972f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *CastExn = 973f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.casted"); 974b29b12d494babf061201ffbcbcacddd21abec50eJohn McCall 975b29b12d494babf061201ffbcbcacddd21abec50eJohn McCall switch (CatchType.getQualifiers().getObjCLifetime()) { 976b29b12d494babf061201ffbcbcacddd21abec50eJohn McCall case Qualifiers::OCL_Strong: 977b29b12d494babf061201ffbcbcacddd21abec50eJohn McCall CastExn = CGF.EmitARCRetainNonBlock(CastExn); 978b29b12d494babf061201ffbcbcacddd21abec50eJohn McCall // fallthrough 979b29b12d494babf061201ffbcbcacddd21abec50eJohn McCall 980b29b12d494babf061201ffbcbcacddd21abec50eJohn McCall case Qualifiers::OCL_None: 981b29b12d494babf061201ffbcbcacddd21abec50eJohn McCall case Qualifiers::OCL_ExplicitNone: 982b29b12d494babf061201ffbcbcacddd21abec50eJohn McCall case Qualifiers::OCL_Autoreleasing: 983b29b12d494babf061201ffbcbcacddd21abec50eJohn McCall CGF.Builder.CreateStore(CastExn, ParamAddr); 984b29b12d494babf061201ffbcbcacddd21abec50eJohn McCall return; 985b29b12d494babf061201ffbcbcacddd21abec50eJohn McCall 986b29b12d494babf061201ffbcbcacddd21abec50eJohn McCall case Qualifiers::OCL_Weak: 987b29b12d494babf061201ffbcbcacddd21abec50eJohn McCall CGF.EmitARCInitWeak(ParamAddr, CastExn); 988b29b12d494babf061201ffbcbcacddd21abec50eJohn McCall return; 989b29b12d494babf061201ffbcbcacddd21abec50eJohn McCall } 990b29b12d494babf061201ffbcbcacddd21abec50eJohn McCall llvm_unreachable("bad ownership qualifier!"); 991f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 9922bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 993f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Otherwise, it returns a pointer into the exception object. 9942bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 9952acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok 996f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::Value *Cast = CGF.Builder.CreateBitCast(AdjustedExn, PtrTy); 9972bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 9989d232c884ea9872d6555df0fd7359699819bc1f1John McCall LValue srcLV = CGF.MakeNaturalAlignAddrLValue(Cast, CatchType); 9999d232c884ea9872d6555df0fd7359699819bc1f1John McCall LValue destLV = CGF.MakeAddrLValue(ParamAddr, CatchType, 10009d232c884ea9872d6555df0fd7359699819bc1f1John McCall CGF.getContext().getDeclAlign(&CatchParam)); 10019d232c884ea9872d6555df0fd7359699819bc1f1John McCall switch (TEK) { 10029d232c884ea9872d6555df0fd7359699819bc1f1John McCall case TEK_Complex: 10034ee7dc2369c1f0257a73b2e83a7d38fdebdd9176Nick Lewycky CGF.EmitStoreOfComplex(CGF.EmitLoadOfComplex(srcLV, Loc), destLV, 10049d232c884ea9872d6555df0fd7359699819bc1f1John McCall /*init*/ true); 10059d232c884ea9872d6555df0fd7359699819bc1f1John McCall return; 10069d232c884ea9872d6555df0fd7359699819bc1f1John McCall case TEK_Scalar: { 10074ee7dc2369c1f0257a73b2e83a7d38fdebdd9176Nick Lewycky llvm::Value *ExnLoad = CGF.EmitLoadOfScalar(srcLV, Loc); 10089d232c884ea9872d6555df0fd7359699819bc1f1John McCall CGF.EmitStoreOfScalar(ExnLoad, destLV, /*init*/ true); 10099d232c884ea9872d6555df0fd7359699819bc1f1John McCall return; 1010f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 10119d232c884ea9872d6555df0fd7359699819bc1f1John McCall case TEK_Aggregate: 10129d232c884ea9872d6555df0fd7359699819bc1f1John McCall llvm_unreachable("evaluation kind filtered out!"); 10139d232c884ea9872d6555df0fd7359699819bc1f1John McCall } 10149d232c884ea9872d6555df0fd7359699819bc1f1John McCall llvm_unreachable("bad evaluation kind"); 1015f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 10160f590be3808365e851352543faa6acbece50b686Mike Stump 1017acff696118d98c3acd09a16b96c95807057b5c99John McCall assert(isa<RecordType>(CatchType) && "unexpected catch type!"); 1018b2c9c0b1c5e25cfbee1403cde12b98f180e6b315Mike Stump 10192acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::Type *PtrTy = LLVMCatchTy->getPointerTo(0); // addrspace 0 ok 1020f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1021acff696118d98c3acd09a16b96c95807057b5c99John McCall // Check for a copy expression. If we don't have a copy expression, 1022acff696118d98c3acd09a16b96c95807057b5c99John McCall // that means a trivial copy is okay. 1023e996ffd240f20a1048179d7727a6ee3227261921John McCall const Expr *copyExpr = CatchParam.getInit(); 1024e996ffd240f20a1048179d7727a6ee3227261921John McCall if (!copyExpr) { 1025acff696118d98c3acd09a16b96c95807057b5c99John McCall llvm::Value *rawAdjustedExn = CallBeginCatch(CGF, Exn, true); 1026acff696118d98c3acd09a16b96c95807057b5c99John McCall llvm::Value *adjustedExn = CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy); 1027649b4a1a9b5e6f768ca0cb84bd97b00f51083e15Chad Rosier CGF.EmitAggregateCopy(ParamAddr, adjustedExn, CatchType); 1028f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return; 1029f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 1030f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1031f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // We have to call __cxa_get_exception_ptr to get the adjusted 1032f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // pointer before copying. 1033e996ffd240f20a1048179d7727a6ee3227261921John McCall llvm::CallInst *rawAdjustedExn = 1034bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall CGF.EmitNounwindRuntimeCall(getGetExceptionPtrFn(CGF.CGM), Exn); 1035f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1036e996ffd240f20a1048179d7727a6ee3227261921John McCall // Cast that to the appropriate type. 1037e996ffd240f20a1048179d7727a6ee3227261921John McCall llvm::Value *adjustedExn = CGF.Builder.CreateBitCast(rawAdjustedExn, PtrTy); 1038f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1039e996ffd240f20a1048179d7727a6ee3227261921John McCall // The copy expression is defined in terms of an OpaqueValueExpr. 1040e996ffd240f20a1048179d7727a6ee3227261921John McCall // Find it and map it to the adjusted expression. 1041e996ffd240f20a1048179d7727a6ee3227261921John McCall CodeGenFunction::OpaqueValueMapping 104256ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall opaque(CGF, OpaqueValueExpr::findInCopyConstruct(copyExpr), 104356ca35d396d8692c384c785f9aeebcf22563fe1eJohn McCall CGF.MakeAddrLValue(adjustedExn, CatchParam.getType())); 1044f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1045f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Call the copy ctor in a terminate scope. 1046f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.EHStack.pushTerminate(); 1047e996ffd240f20a1048179d7727a6ee3227261921John McCall 1048e996ffd240f20a1048179d7727a6ee3227261921John McCall // Perform the copy construction. 1049d7722d9d76a851e7897f4127626616d3b1b8e530Eli Friedman CharUnits Alignment = CGF.getContext().getDeclAlign(&CatchParam); 1050f394078fde147dcf27e9b6a7965517388d64dcb6Eli Friedman CGF.EmitAggExpr(copyExpr, 1051f394078fde147dcf27e9b6a7965517388d64dcb6Eli Friedman AggValueSlot::forAddr(ParamAddr, Alignment, Qualifiers(), 1052f394078fde147dcf27e9b6a7965517388d64dcb6Eli Friedman AggValueSlot::IsNotDestructed, 1053f394078fde147dcf27e9b6a7965517388d64dcb6Eli Friedman AggValueSlot::DoesNotNeedGCBarriers, 1054649b4a1a9b5e6f768ca0cb84bd97b00f51083e15Chad Rosier AggValueSlot::IsNotAliased)); 1055e996ffd240f20a1048179d7727a6ee3227261921John McCall 1056e996ffd240f20a1048179d7727a6ee3227261921John McCall // Leave the terminate scope. 1057f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGF.EHStack.popTerminate(); 1058f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1059e996ffd240f20a1048179d7727a6ee3227261921John McCall // Undo the opaque value mapping. 1060e996ffd240f20a1048179d7727a6ee3227261921John McCall opaque.pop(); 1061e996ffd240f20a1048179d7727a6ee3227261921John McCall 1062f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Finally we can call __cxa_begin_catch. 10638e3f86193995c47ee0d229e4336c3382410f09f5John McCall CallBeginCatch(CGF, Exn, true); 1064f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 1065f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1066f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// Begins a catch statement by initializing the catch variable and 1067f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// calling __cxa_begin_catch. 1068e996ffd240f20a1048179d7727a6ee3227261921John McCallstatic void BeginCatch(CodeGenFunction &CGF, const CXXCatchStmt *S) { 1069f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // We have to be very careful with the ordering of cleanups here: 1070f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // C++ [except.throw]p4: 1071f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // The destruction [of the exception temporary] occurs 1072f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // immediately after the destruction of the object declared in 1073f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // the exception-declaration in the handler. 1074f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // 1075f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // So the precise ordering is: 1076f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // 1. Construct catch variable. 1077f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // 2. __cxa_begin_catch 1078f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // 3. Enter __cxa_end_catch cleanup 1079f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // 4. Enter dtor cleanup 1080f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // 108134695856c0e67b3765b46304cc71b5d2cd5b71c7John McCall // We do this by using a slightly abnormal initialization process. 108234695856c0e67b3765b46304cc71b5d2cd5b71c7John McCall // Delegation sequence: 1083f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // - ExitCXXTryStmt opens a RunCleanupsScope 108434695856c0e67b3765b46304cc71b5d2cd5b71c7John McCall // - EmitAutoVarAlloca creates the variable and debug info 1085f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // - InitCatchParam initializes the variable from the exception 108634695856c0e67b3765b46304cc71b5d2cd5b71c7John McCall // - CallBeginCatch calls __cxa_begin_catch 108734695856c0e67b3765b46304cc71b5d2cd5b71c7John McCall // - CallBeginCatch enters the __cxa_end_catch cleanup 108834695856c0e67b3765b46304cc71b5d2cd5b71c7John McCall // - EmitAutoVarCleanups enters the variable destructor cleanup 1089f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // - EmitCXXTryStmt emits the code for the catch body 1090f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // - EmitCXXTryStmt close the RunCleanupsScope 1091f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1092f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall VarDecl *CatchParam = S->getExceptionDecl(); 1093f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (!CatchParam) { 1094ae270598d5c7a9a283d4b3ddce53b151c6e2b182Bill Wendling llvm::Value *Exn = CGF.getExceptionFromSlot(); 10958e3f86193995c47ee0d229e4336c3382410f09f5John McCall CallBeginCatch(CGF, Exn, true); 1096f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return; 1097f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 1098f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1099f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Emit the local. 110034695856c0e67b3765b46304cc71b5d2cd5b71c7John McCall CodeGenFunction::AutoVarEmission var = CGF.EmitAutoVarAlloca(*CatchParam); 11014ee7dc2369c1f0257a73b2e83a7d38fdebdd9176Nick Lewycky InitCatchParam(CGF, *CatchParam, var.getObjectAddress(CGF), S->getLocStart()); 110234695856c0e67b3765b46304cc71b5d2cd5b71c7John McCall CGF.EmitAutoVarCleanups(var); 1103f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 1104f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1105777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall/// Emit the structure of the dispatch block for the given catch scope. 1106777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall/// It is an invariant that the dispatch block already exists. 1107777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCallstatic void emitCatchDispatchBlock(CodeGenFunction &CGF, 1108777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall EHCatchScope &catchScope) { 1109777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall llvm::BasicBlock *dispatchBlock = catchScope.getCachedEHDispatchBlock(); 1110777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall assert(dispatchBlock); 1111777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 1112777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // If there's only a single catch-all, getEHDispatchBlock returned 1113777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // that catch-all as the dispatch block. 1114777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall if (catchScope.getNumHandlers() == 1 && 1115777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall catchScope.getHandler(0).isCatchAll()) { 1116777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall assert(dispatchBlock == catchScope.getHandler(0).Block); 1117777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall return; 1118777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall } 1119777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 1120777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall CGBuilderTy::InsertPoint savedIP = CGF.Builder.saveIP(); 1121777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall CGF.EmitBlockAfterUses(dispatchBlock); 1122777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 1123777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // Select the right handler. 1124777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall llvm::Value *llvm_eh_typeid_for = 1125777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall CGF.CGM.getIntrinsic(llvm::Intrinsic::eh_typeid_for); 1126777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 1127777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // Load the selector value. 1128ae270598d5c7a9a283d4b3ddce53b151c6e2b182Bill Wendling llvm::Value *selector = CGF.getSelectorFromSlot(); 1129777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 1130777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // Test against each of the exception types we claim to catch. 1131777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall for (unsigned i = 0, e = catchScope.getNumHandlers(); ; ++i) { 1132777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall assert(i < e && "ran off end of handlers!"); 1133777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall const EHCatchScope::Handler &handler = catchScope.getHandler(i); 1134777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 1135777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall llvm::Value *typeValue = handler.Type; 1136777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall assert(typeValue && "fell into catch-all case!"); 1137777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall typeValue = CGF.Builder.CreateBitCast(typeValue, CGF.Int8PtrTy); 1138777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 1139777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // Figure out the next block. 1140777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall bool nextIsEnd; 1141777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall llvm::BasicBlock *nextBlock; 1142777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 1143777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // If this is the last handler, we're at the end, and the next 1144777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // block is the block for the enclosing EH scope. 1145777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall if (i + 1 == e) { 1146777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall nextBlock = CGF.getEHDispatchBlock(catchScope.getEnclosingEHScope()); 1147777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall nextIsEnd = true; 1148777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 1149777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // If the next handler is a catch-all, we're at the end, and the 1150777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // next block is that handler. 1151777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall } else if (catchScope.getHandler(i+1).isCatchAll()) { 1152777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall nextBlock = catchScope.getHandler(i+1).Block; 1153777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall nextIsEnd = true; 1154777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 1155777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // Otherwise, we're not at the end and we need a new block. 1156777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall } else { 1157777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall nextBlock = CGF.createBasicBlock("catch.fallthrough"); 1158777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall nextIsEnd = false; 1159777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall } 1160777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 1161777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // Figure out the catch type's index in the LSDA's type table. 1162777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall llvm::CallInst *typeIndex = 1163777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall CGF.Builder.CreateCall(llvm_eh_typeid_for, typeValue); 1164777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall typeIndex->setDoesNotThrow(); 1165777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 1166777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall llvm::Value *matchesTypeIndex = 1167777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall CGF.Builder.CreateICmpEQ(selector, typeIndex, "matches"); 1168777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall CGF.Builder.CreateCondBr(matchesTypeIndex, handler.Block, nextBlock); 1169777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 1170777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // If the next handler is a catch-all, we're completely done. 1171777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall if (nextIsEnd) { 1172777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall CGF.Builder.restoreIP(savedIP); 1173777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall return; 1174777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall } 1175e8e92b9dccc362be33a7f9bb84a114b18db65b10Ahmed Charles // Otherwise we need to emit and continue at that block. 1176e8e92b9dccc362be33a7f9bb84a114b18db65b10Ahmed Charles CGF.EmitBlock(nextBlock); 1177777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall } 1178777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall} 1179777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 1180777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCallvoid CodeGenFunction::popCatchScope() { 1181777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall EHCatchScope &catchScope = cast<EHCatchScope>(*EHStack.begin()); 1182777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall if (catchScope.hasEHBranches()) 1183777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall emitCatchDispatchBlock(*this, catchScope); 1184777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall EHStack.popCatch(); 1185777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall} 1186777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 118759a7000a79118e4c140885ccbb2ac6a686a73092John McCallvoid CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S, bool IsFnTryBlock) { 1188f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall unsigned NumHandlers = S.getNumHandlers(); 1189f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHCatchScope &CatchScope = cast<EHCatchScope>(*EHStack.begin()); 1190f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall assert(CatchScope.getNumHandlers() == NumHandlers); 1191f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1192777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // If the catch was not required, bail out now. 1193777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall if (!CatchScope.hasEHBranches()) { 1194651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CatchScope.clearHandlerBlocks(); 1195777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall EHStack.popCatch(); 1196777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall return; 1197777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall } 1198777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 1199777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // Emit the structure of the EH dispatch for this catch. 1200777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall emitCatchDispatchBlock(*this, CatchScope); 1201777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 1202f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Copy the handler blocks off before we pop the EH stack. Emitting 1203f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // the handlers might scribble on this memory. 12045f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner SmallVector<EHCatchScope::Handler, 8> Handlers(NumHandlers); 1205f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall memcpy(Handlers.data(), CatchScope.begin(), 1206f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall NumHandlers * sizeof(EHCatchScope::Handler)); 1207777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 1208f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EHStack.popCatch(); 1209f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1210f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // The fall-through block. 1211f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall llvm::BasicBlock *ContBB = createBasicBlock("try.cont"); 1212f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1213f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // We just emitted the body of the try; jump to the continue block. 1214f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (HaveInsertPoint()) 1215f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateBr(ContBB); 1216f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1217f5533019fb70d62917fd080f6152b6469e2c6cd5John McCall // Determine if we need an implicit rethrow for all these catch handlers; 1218f5533019fb70d62917fd080f6152b6469e2c6cd5John McCall // see the comment below. 1219f5533019fb70d62917fd080f6152b6469e2c6cd5John McCall bool doImplicitRethrow = false; 122059a7000a79118e4c140885ccbb2ac6a686a73092John McCall if (IsFnTryBlock) 1221f5533019fb70d62917fd080f6152b6469e2c6cd5John McCall doImplicitRethrow = isa<CXXDestructorDecl>(CurCodeDecl) || 1222f5533019fb70d62917fd080f6152b6469e2c6cd5John McCall isa<CXXConstructorDecl>(CurCodeDecl); 122359a7000a79118e4c140885ccbb2ac6a686a73092John McCall 1224777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // Perversely, we emit the handlers backwards precisely because we 1225777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // want them to appear in source order. In all of these cases, the 1226777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // catch block will have exactly one predecessor, which will be a 1227777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // particular block in the catch dispatch. However, in the case of 1228777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // a catch-all, one of the dispatch blocks will branch to two 1229777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // different handlers, and EmitBlockAfterUses will cause the second 1230777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall // handler to be moved before the first. 1231777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall for (unsigned I = NumHandlers; I != 0; --I) { 1232777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall llvm::BasicBlock *CatchBlock = Handlers[I-1].Block; 1233777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall EmitBlockAfterUses(CatchBlock); 1234f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1235f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Catch the exception if this isn't a catch-all. 1236777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall const CXXCatchStmt *C = S.getHandler(I-1); 1237f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1238f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Enter a cleanup scope, including the catch variable and the 1239f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // end-catch. 1240f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall RunCleanupsScope CatchScope(*this); 1241f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1242f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Initialize the catch variable and set up the cleanups. 1243f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall BeginCatch(*this, C); 1244f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1245651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines // Emit the PGO counter increment. 1246651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines RegionCounter CatchCnt = getPGORegionCounter(C); 1247651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines CatchCnt.beginRegion(Builder); 1248651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines 1249f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Perform the body of the catch. 1250f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EmitStmt(C->getHandlerBlock()); 1251f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1252f5533019fb70d62917fd080f6152b6469e2c6cd5John McCall // [except.handle]p11: 1253f5533019fb70d62917fd080f6152b6469e2c6cd5John McCall // The currently handled exception is rethrown if control 1254f5533019fb70d62917fd080f6152b6469e2c6cd5John McCall // reaches the end of a handler of the function-try-block of a 1255f5533019fb70d62917fd080f6152b6469e2c6cd5John McCall // constructor or destructor. 1256f5533019fb70d62917fd080f6152b6469e2c6cd5John McCall 1257f5533019fb70d62917fd080f6152b6469e2c6cd5John McCall // It is important that we only do this on fallthrough and not on 1258f5533019fb70d62917fd080f6152b6469e2c6cd5John McCall // return. Note that it's illegal to put a return in a 1259f5533019fb70d62917fd080f6152b6469e2c6cd5John McCall // constructor function-try-block's catch handler (p14), so this 1260f5533019fb70d62917fd080f6152b6469e2c6cd5John McCall // really only applies to destructors. 1261f5533019fb70d62917fd080f6152b6469e2c6cd5John McCall if (doImplicitRethrow && HaveInsertPoint()) { 1262bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall EmitRuntimeCallOrInvoke(getReThrowFn(CGM)); 1263f5533019fb70d62917fd080f6152b6469e2c6cd5John McCall Builder.CreateUnreachable(); 1264f5533019fb70d62917fd080f6152b6469e2c6cd5John McCall Builder.ClearInsertionPoint(); 1265f5533019fb70d62917fd080f6152b6469e2c6cd5John McCall } 1266f5533019fb70d62917fd080f6152b6469e2c6cd5John McCall 1267f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Fall out through the catch cleanups. 1268f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CatchScope.ForceCleanup(); 1269f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1270f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Branch out of the try. 1271f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (HaveInsertPoint()) 1272f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.CreateBr(ContBB); 1273f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall } 12742bf701ee4babb5c4a9ea99ca4675c5ef040bd402Mike Stump 1275651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines RegionCounter ContCnt = getPGORegionCounter(&S); 1276f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall EmitBlock(ContBB); 1277651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines ContCnt.beginRegion(Builder); 1278f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 1279f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 128055b20fc514678ff8ae1627cd9aef047d1f780119John McCallnamespace { 12811f0fca54676cfa8616e7f3cd7a26788ab937e3cdJohn McCall struct CallEndCatchForFinally : EHScopeStack::Cleanup { 128255b20fc514678ff8ae1627cd9aef047d1f780119John McCall llvm::Value *ForEHVar; 128355b20fc514678ff8ae1627cd9aef047d1f780119John McCall llvm::Value *EndCatchFn; 128455b20fc514678ff8ae1627cd9aef047d1f780119John McCall CallEndCatchForFinally(llvm::Value *ForEHVar, llvm::Value *EndCatchFn) 128555b20fc514678ff8ae1627cd9aef047d1f780119John McCall : ForEHVar(ForEHVar), EndCatchFn(EndCatchFn) {} 128655b20fc514678ff8ae1627cd9aef047d1f780119John McCall 1287651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void Emit(CodeGenFunction &CGF, Flags flags) override { 128855b20fc514678ff8ae1627cd9aef047d1f780119John McCall llvm::BasicBlock *EndCatchBB = CGF.createBasicBlock("finally.endcatch"); 128955b20fc514678ff8ae1627cd9aef047d1f780119John McCall llvm::BasicBlock *CleanupContBB = 129055b20fc514678ff8ae1627cd9aef047d1f780119John McCall CGF.createBasicBlock("finally.cleanup.cont"); 129155b20fc514678ff8ae1627cd9aef047d1f780119John McCall 129255b20fc514678ff8ae1627cd9aef047d1f780119John McCall llvm::Value *ShouldEndCatch = 129355b20fc514678ff8ae1627cd9aef047d1f780119John McCall CGF.Builder.CreateLoad(ForEHVar, "finally.endcatch"); 129455b20fc514678ff8ae1627cd9aef047d1f780119John McCall CGF.Builder.CreateCondBr(ShouldEndCatch, EndCatchBB, CleanupContBB); 129555b20fc514678ff8ae1627cd9aef047d1f780119John McCall CGF.EmitBlock(EndCatchBB); 1296bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall CGF.EmitRuntimeCallOrInvoke(EndCatchFn); // catch-all, so might throw 129755b20fc514678ff8ae1627cd9aef047d1f780119John McCall CGF.EmitBlock(CleanupContBB); 129855b20fc514678ff8ae1627cd9aef047d1f780119John McCall } 129955b20fc514678ff8ae1627cd9aef047d1f780119John McCall }; 130077199713ab56f87ffad9a535ff2a0877704eed87John McCall 13011f0fca54676cfa8616e7f3cd7a26788ab937e3cdJohn McCall struct PerformFinally : EHScopeStack::Cleanup { 130277199713ab56f87ffad9a535ff2a0877704eed87John McCall const Stmt *Body; 130377199713ab56f87ffad9a535ff2a0877704eed87John McCall llvm::Value *ForEHVar; 130477199713ab56f87ffad9a535ff2a0877704eed87John McCall llvm::Value *EndCatchFn; 130577199713ab56f87ffad9a535ff2a0877704eed87John McCall llvm::Value *RethrowFn; 130677199713ab56f87ffad9a535ff2a0877704eed87John McCall llvm::Value *SavedExnVar; 130777199713ab56f87ffad9a535ff2a0877704eed87John McCall 130877199713ab56f87ffad9a535ff2a0877704eed87John McCall PerformFinally(const Stmt *Body, llvm::Value *ForEHVar, 130977199713ab56f87ffad9a535ff2a0877704eed87John McCall llvm::Value *EndCatchFn, 131077199713ab56f87ffad9a535ff2a0877704eed87John McCall llvm::Value *RethrowFn, llvm::Value *SavedExnVar) 131177199713ab56f87ffad9a535ff2a0877704eed87John McCall : Body(Body), ForEHVar(ForEHVar), EndCatchFn(EndCatchFn), 131277199713ab56f87ffad9a535ff2a0877704eed87John McCall RethrowFn(RethrowFn), SavedExnVar(SavedExnVar) {} 131377199713ab56f87ffad9a535ff2a0877704eed87John McCall 1314651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines void Emit(CodeGenFunction &CGF, Flags flags) override { 131577199713ab56f87ffad9a535ff2a0877704eed87John McCall // Enter a cleanup to call the end-catch function if one was provided. 131677199713ab56f87ffad9a535ff2a0877704eed87John McCall if (EndCatchFn) 13171f0fca54676cfa8616e7f3cd7a26788ab937e3cdJohn McCall CGF.EHStack.pushCleanup<CallEndCatchForFinally>(NormalAndEHCleanup, 13181f0fca54676cfa8616e7f3cd7a26788ab937e3cdJohn McCall ForEHVar, EndCatchFn); 131977199713ab56f87ffad9a535ff2a0877704eed87John McCall 1320d96a8e771ca9f406f0fa1dd4639997335ae444a7John McCall // Save the current cleanup destination in case there are 1321d96a8e771ca9f406f0fa1dd4639997335ae444a7John McCall // cleanups in the finally block. 1322d96a8e771ca9f406f0fa1dd4639997335ae444a7John McCall llvm::Value *SavedCleanupDest = 1323d96a8e771ca9f406f0fa1dd4639997335ae444a7John McCall CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot(), 1324d96a8e771ca9f406f0fa1dd4639997335ae444a7John McCall "cleanup.dest.saved"); 1325d96a8e771ca9f406f0fa1dd4639997335ae444a7John McCall 132677199713ab56f87ffad9a535ff2a0877704eed87John McCall // Emit the finally block. 132777199713ab56f87ffad9a535ff2a0877704eed87John McCall CGF.EmitStmt(Body); 132877199713ab56f87ffad9a535ff2a0877704eed87John McCall 132977199713ab56f87ffad9a535ff2a0877704eed87John McCall // If the end of the finally is reachable, check whether this was 133077199713ab56f87ffad9a535ff2a0877704eed87John McCall // for EH. If so, rethrow. 133177199713ab56f87ffad9a535ff2a0877704eed87John McCall if (CGF.HaveInsertPoint()) { 133277199713ab56f87ffad9a535ff2a0877704eed87John McCall llvm::BasicBlock *RethrowBB = CGF.createBasicBlock("finally.rethrow"); 133377199713ab56f87ffad9a535ff2a0877704eed87John McCall llvm::BasicBlock *ContBB = CGF.createBasicBlock("finally.cont"); 133477199713ab56f87ffad9a535ff2a0877704eed87John McCall 133577199713ab56f87ffad9a535ff2a0877704eed87John McCall llvm::Value *ShouldRethrow = 133677199713ab56f87ffad9a535ff2a0877704eed87John McCall CGF.Builder.CreateLoad(ForEHVar, "finally.shouldthrow"); 133777199713ab56f87ffad9a535ff2a0877704eed87John McCall CGF.Builder.CreateCondBr(ShouldRethrow, RethrowBB, ContBB); 133877199713ab56f87ffad9a535ff2a0877704eed87John McCall 133977199713ab56f87ffad9a535ff2a0877704eed87John McCall CGF.EmitBlock(RethrowBB); 134077199713ab56f87ffad9a535ff2a0877704eed87John McCall if (SavedExnVar) { 1341bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall CGF.EmitRuntimeCallOrInvoke(RethrowFn, 1342bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall CGF.Builder.CreateLoad(SavedExnVar)); 134377199713ab56f87ffad9a535ff2a0877704eed87John McCall } else { 1344bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall CGF.EmitRuntimeCallOrInvoke(RethrowFn); 134577199713ab56f87ffad9a535ff2a0877704eed87John McCall } 134677199713ab56f87ffad9a535ff2a0877704eed87John McCall CGF.Builder.CreateUnreachable(); 134777199713ab56f87ffad9a535ff2a0877704eed87John McCall 134877199713ab56f87ffad9a535ff2a0877704eed87John McCall CGF.EmitBlock(ContBB); 1349d96a8e771ca9f406f0fa1dd4639997335ae444a7John McCall 1350d96a8e771ca9f406f0fa1dd4639997335ae444a7John McCall // Restore the cleanup destination. 1351d96a8e771ca9f406f0fa1dd4639997335ae444a7John McCall CGF.Builder.CreateStore(SavedCleanupDest, 1352d96a8e771ca9f406f0fa1dd4639997335ae444a7John McCall CGF.getNormalCleanupDestSlot()); 135377199713ab56f87ffad9a535ff2a0877704eed87John McCall } 135477199713ab56f87ffad9a535ff2a0877704eed87John McCall 135577199713ab56f87ffad9a535ff2a0877704eed87John McCall // Leave the end-catch cleanup. As an optimization, pretend that 135677199713ab56f87ffad9a535ff2a0877704eed87John McCall // the fallthrough path was inaccessible; we've dynamically proven 135777199713ab56f87ffad9a535ff2a0877704eed87John McCall // that we're not in the EH case along that path. 135877199713ab56f87ffad9a535ff2a0877704eed87John McCall if (EndCatchFn) { 135977199713ab56f87ffad9a535ff2a0877704eed87John McCall CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP(); 136077199713ab56f87ffad9a535ff2a0877704eed87John McCall CGF.PopCleanupBlock(); 136177199713ab56f87ffad9a535ff2a0877704eed87John McCall CGF.Builder.restoreIP(SavedIP); 136277199713ab56f87ffad9a535ff2a0877704eed87John McCall } 136377199713ab56f87ffad9a535ff2a0877704eed87John McCall 136477199713ab56f87ffad9a535ff2a0877704eed87John McCall // Now make sure we actually have an insertion point or the 136577199713ab56f87ffad9a535ff2a0877704eed87John McCall // cleanup gods will hate us. 136677199713ab56f87ffad9a535ff2a0877704eed87John McCall CGF.EnsureInsertPoint(); 136777199713ab56f87ffad9a535ff2a0877704eed87John McCall } 136877199713ab56f87ffad9a535ff2a0877704eed87John McCall }; 136955b20fc514678ff8ae1627cd9aef047d1f780119John McCall} 137055b20fc514678ff8ae1627cd9aef047d1f780119John McCall 1371f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// Enters a finally block for an implementation using zero-cost 1372f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// exceptions. This is mostly general, but hard-codes some 1373f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall/// language/ABI-specific behavior in the catch-all sections. 1374d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCallvoid CodeGenFunction::FinallyInfo::enter(CodeGenFunction &CGF, 1375d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall const Stmt *body, 1376d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall llvm::Constant *beginCatchFn, 1377d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall llvm::Constant *endCatchFn, 1378d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall llvm::Constant *rethrowFn) { 13796bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines assert((beginCatchFn != nullptr) == (endCatchFn != nullptr) && 1380f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall "begin/end catch functions not paired"); 1381d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall assert(rethrowFn && "rethrow function is required"); 1382d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall 1383d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall BeginCatchFn = beginCatchFn; 1384f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1385f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // The rethrow function has one of the following two types: 1386f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // void (*)() 1387f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // void (*)(void*) 1388f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // In the latter case we need to pass it the exception object. 1389f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // But we can't use the exception slot because the @finally might 1390f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // have a landing pad (which would overwrite the exception slot). 13912acc6e3feda5e4f7d9009bdcf8b1cd777fecfe2dChris Lattner llvm::FunctionType *rethrowFnTy = 1392f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall cast<llvm::FunctionType>( 1393d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall cast<llvm::PointerType>(rethrowFn->getType())->getElementType()); 13946bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines SavedExnVar = nullptr; 1395d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall if (rethrowFnTy->getNumParams()) 1396d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall SavedExnVar = CGF.CreateTempAlloca(CGF.Int8PtrTy, "finally.exn"); 1397f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1398f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // A finally block is a statement which must be executed on any edge 1399f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // out of a given scope. Unlike a cleanup, the finally block may 1400f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // contain arbitrary control flow leading out of itself. In 1401f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // addition, finally blocks should always be executed, even if there 1402f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // are no catch handlers higher on the stack. Therefore, we 1403f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // surround the protected scope with a combination of a normal 1404f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // cleanup (to catch attempts to break out of the block via normal 1405f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // control flow) and an EH catch-all (semantically "outside" any try 1406f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // statement to which the finally block might have been attached). 1407f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // The finally block itself is generated in the context of a cleanup 1408f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // which conditionally leaves the catch-all. 1409f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1410f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Jump destination for performing the finally block on an exception 1411f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // edge. We'll never actually reach this block, so unreachable is 1412f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // fine. 1413d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall RethrowDest = CGF.getJumpDestInCurrentScope(CGF.getUnreachableBlock()); 1414f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1415f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Whether the finally block is being executed for EH purposes. 1416d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall ForEHVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(), "finally.for-eh"); 1417d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall CGF.Builder.CreateStore(CGF.Builder.getFalse(), ForEHVar); 1418f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1419f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Enter a normal cleanup which will perform the @finally block. 1420d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall CGF.EHStack.pushCleanup<PerformFinally>(NormalCleanup, body, 1421d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall ForEHVar, endCatchFn, 1422d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall rethrowFn, SavedExnVar); 1423f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1424f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Enter a catch-all scope. 1425d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall llvm::BasicBlock *catchBB = CGF.createBasicBlock("finally.catchall"); 1426d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall EHCatchScope *catchScope = CGF.EHStack.pushCatch(1); 1427d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall catchScope->setCatchAllHandler(0, catchBB); 1428d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall} 1429f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1430d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCallvoid CodeGenFunction::FinallyInfo::exit(CodeGenFunction &CGF) { 1431d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall // Leave the finally catch-all. 1432d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall EHCatchScope &catchScope = cast<EHCatchScope>(*CGF.EHStack.begin()); 1433d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall llvm::BasicBlock *catchBB = catchScope.getHandler(0).Block; 1434777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall 1435777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall CGF.popCatchScope(); 1436f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1437d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall // If there are any references to the catch-all block, emit it. 1438d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall if (catchBB->use_empty()) { 1439d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall delete catchBB; 1440d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall } else { 1441d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall CGBuilderTy::InsertPoint savedIP = CGF.Builder.saveAndClearIP(); 1442d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall CGF.EmitBlock(catchBB); 1443f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 14446bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines llvm::Value *exn = nullptr; 1445f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1446d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall // If there's a begin-catch function, call it. 1447d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall if (BeginCatchFn) { 1448ae270598d5c7a9a283d4b3ddce53b151c6e2b182Bill Wendling exn = CGF.getExceptionFromSlot(); 1449bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall CGF.EmitNounwindRuntimeCall(BeginCatchFn, exn); 1450d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall } 1451f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1452d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall // If we need to remember the exception pointer to rethrow later, do so. 1453d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall if (SavedExnVar) { 1454ae270598d5c7a9a283d4b3ddce53b151c6e2b182Bill Wendling if (!exn) exn = CGF.getExceptionFromSlot(); 1455d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall CGF.Builder.CreateStore(exn, SavedExnVar); 1456d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall } 1457f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1458d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall // Tell the cleanups in the finally block that we're do this for EH. 1459d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall CGF.Builder.CreateStore(CGF.Builder.getTrue(), ForEHVar); 1460f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1461d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall // Thread a jump through the finally cleanup. 1462d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall CGF.EmitBranchThroughCleanup(RethrowDest); 1463f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1464d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall CGF.Builder.restoreIP(savedIP); 1465d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall } 1466f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1467d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall // Finally, leave the @finally cleanup. 1468d768e9d29abe1ac1ccc3ed63f2dce835d9bab342John McCall CGF.PopCleanupBlock(); 1469f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall} 1470f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 147166b22771fc0a1dba598e50469f2961048e7edd55John McCall/// In a terminate landing pad, should we use __clang__call_terminate 147266b22771fc0a1dba598e50469f2961048e7edd55John McCall/// or just a naked call to std::terminate? 147366b22771fc0a1dba598e50469f2961048e7edd55John McCall/// 147466b22771fc0a1dba598e50469f2961048e7edd55John McCall/// __clang_call_terminate calls __cxa_begin_catch, which then allows 147566b22771fc0a1dba598e50469f2961048e7edd55John McCall/// std::terminate to usefully report something about the 147666b22771fc0a1dba598e50469f2961048e7edd55John McCall/// violating exception. 147766b22771fc0a1dba598e50469f2961048e7edd55John McCallstatic bool useClangCallTerminate(CodeGenModule &CGM) { 147866b22771fc0a1dba598e50469f2961048e7edd55John McCall // Only do this for Itanium-family ABIs in C++ mode. 147966b22771fc0a1dba598e50469f2961048e7edd55John McCall return (CGM.getLangOpts().CPlusPlus && 148066b22771fc0a1dba598e50469f2961048e7edd55John McCall CGM.getTarget().getCXXABI().isItaniumFamily()); 148166b22771fc0a1dba598e50469f2961048e7edd55John McCall} 148266b22771fc0a1dba598e50469f2961048e7edd55John McCall 148366b22771fc0a1dba598e50469f2961048e7edd55John McCall/// Get or define the following function: 148466b22771fc0a1dba598e50469f2961048e7edd55John McCall/// void @__clang_call_terminate(i8* %exn) nounwind noreturn 148566b22771fc0a1dba598e50469f2961048e7edd55John McCall/// This code is used only in C++. 148666b22771fc0a1dba598e50469f2961048e7edd55John McCallstatic llvm::Constant *getClangCallTerminateFn(CodeGenModule &CGM) { 148766b22771fc0a1dba598e50469f2961048e7edd55John McCall llvm::FunctionType *fnTy = 148866b22771fc0a1dba598e50469f2961048e7edd55John McCall llvm::FunctionType::get(CGM.VoidTy, CGM.Int8PtrTy, /*IsVarArgs=*/false); 148966b22771fc0a1dba598e50469f2961048e7edd55John McCall llvm::Constant *fnRef = 149066b22771fc0a1dba598e50469f2961048e7edd55John McCall CGM.CreateRuntimeFunction(fnTy, "__clang_call_terminate"); 149166b22771fc0a1dba598e50469f2961048e7edd55John McCall 149266b22771fc0a1dba598e50469f2961048e7edd55John McCall llvm::Function *fn = dyn_cast<llvm::Function>(fnRef); 149366b22771fc0a1dba598e50469f2961048e7edd55John McCall if (fn && fn->empty()) { 149466b22771fc0a1dba598e50469f2961048e7edd55John McCall fn->setDoesNotThrow(); 149566b22771fc0a1dba598e50469f2961048e7edd55John McCall fn->setDoesNotReturn(); 149666b22771fc0a1dba598e50469f2961048e7edd55John McCall 149766b22771fc0a1dba598e50469f2961048e7edd55John McCall // What we really want is to massively penalize inlining without 149866b22771fc0a1dba598e50469f2961048e7edd55John McCall // forbidding it completely. The difference between that and 149966b22771fc0a1dba598e50469f2961048e7edd55John McCall // 'noinline' is negligible. 150066b22771fc0a1dba598e50469f2961048e7edd55John McCall fn->addFnAttr(llvm::Attribute::NoInline); 150166b22771fc0a1dba598e50469f2961048e7edd55John McCall 150266b22771fc0a1dba598e50469f2961048e7edd55John McCall // Allow this function to be shared across translation units, but 150366b22771fc0a1dba598e50469f2961048e7edd55John McCall // we don't want it to turn into an exported symbol. 150466b22771fc0a1dba598e50469f2961048e7edd55John McCall fn->setLinkage(llvm::Function::LinkOnceODRLinkage); 150566b22771fc0a1dba598e50469f2961048e7edd55John McCall fn->setVisibility(llvm::Function::HiddenVisibility); 150666b22771fc0a1dba598e50469f2961048e7edd55John McCall 150766b22771fc0a1dba598e50469f2961048e7edd55John McCall // Set up the function. 150866b22771fc0a1dba598e50469f2961048e7edd55John McCall llvm::BasicBlock *entry = 150966b22771fc0a1dba598e50469f2961048e7edd55John McCall llvm::BasicBlock::Create(CGM.getLLVMContext(), "", fn); 151066b22771fc0a1dba598e50469f2961048e7edd55John McCall CGBuilderTy builder(entry); 151166b22771fc0a1dba598e50469f2961048e7edd55John McCall 151266b22771fc0a1dba598e50469f2961048e7edd55John McCall // Pull the exception pointer out of the parameter list. 151366b22771fc0a1dba598e50469f2961048e7edd55John McCall llvm::Value *exn = &*fn->arg_begin(); 151466b22771fc0a1dba598e50469f2961048e7edd55John McCall 151566b22771fc0a1dba598e50469f2961048e7edd55John McCall // Call __cxa_begin_catch(exn). 1516bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall llvm::CallInst *catchCall = builder.CreateCall(getBeginCatchFn(CGM), exn); 1517bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall catchCall->setDoesNotThrow(); 1518bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall catchCall->setCallingConv(CGM.getRuntimeCC()); 151966b22771fc0a1dba598e50469f2961048e7edd55John McCall 152066b22771fc0a1dba598e50469f2961048e7edd55John McCall // Call std::terminate(). 152166b22771fc0a1dba598e50469f2961048e7edd55John McCall llvm::CallInst *termCall = builder.CreateCall(getTerminateFn(CGM)); 152266b22771fc0a1dba598e50469f2961048e7edd55John McCall termCall->setDoesNotThrow(); 152366b22771fc0a1dba598e50469f2961048e7edd55John McCall termCall->setDoesNotReturn(); 1524bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall termCall->setCallingConv(CGM.getRuntimeCC()); 152566b22771fc0a1dba598e50469f2961048e7edd55John McCall 152666b22771fc0a1dba598e50469f2961048e7edd55John McCall // std::terminate cannot return. 152766b22771fc0a1dba598e50469f2961048e7edd55John McCall builder.CreateUnreachable(); 152866b22771fc0a1dba598e50469f2961048e7edd55John McCall } 152966b22771fc0a1dba598e50469f2961048e7edd55John McCall 153066b22771fc0a1dba598e50469f2961048e7edd55John McCall return fnRef; 153166b22771fc0a1dba598e50469f2961048e7edd55John McCall} 153266b22771fc0a1dba598e50469f2961048e7edd55John McCall 1533f1549f66a8216a78112286e3978cea2c29d6334cJohn McCallllvm::BasicBlock *CodeGenFunction::getTerminateLandingPad() { 1534f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall if (TerminateLandingPad) 1535f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return TerminateLandingPad; 1536f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1537f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); 1538f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1539f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // This will get inserted at the end of the function. 1540f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall TerminateLandingPad = createBasicBlock("terminate.lpad"); 1541f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.SetInsertPoint(TerminateLandingPad); 1542f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1543f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Tell the backend that this is a landing pad. 15444e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie const EHPersonality &Personality = EHPersonality::get(CGM.getLangOpts()); 1545285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling llvm::LandingPadInst *LPadInst = 1546285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling Builder.CreateLandingPad(llvm::StructType::get(Int8PtrTy, Int32Ty, NULL), 1547285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling getOpaquePersonalityFn(CGM, Personality), 0); 1548285cfd8953d4ca4da613a47a0d691f7234068f8cBill Wendling LPadInst->addClause(getCatchAllValue(*this)); 1549f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 155066b22771fc0a1dba598e50469f2961048e7edd55John McCall llvm::CallInst *terminateCall; 155166b22771fc0a1dba598e50469f2961048e7edd55John McCall if (useClangCallTerminate(CGM)) { 155266b22771fc0a1dba598e50469f2961048e7edd55John McCall // Extract out the exception pointer. 155366b22771fc0a1dba598e50469f2961048e7edd55John McCall llvm::Value *exn = Builder.CreateExtractValue(LPadInst, 0); 1554bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall terminateCall = EmitNounwindRuntimeCall(getClangCallTerminateFn(CGM), exn); 155566b22771fc0a1dba598e50469f2961048e7edd55John McCall } else { 1556bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall terminateCall = EmitNounwindRuntimeCall(getTerminateFn(CGM)); 155766b22771fc0a1dba598e50469f2961048e7edd55John McCall } 155866b22771fc0a1dba598e50469f2961048e7edd55John McCall terminateCall->setDoesNotReturn(); 1559d16c2cf1cafa413709aa487cbbd5dc392f1ba1ffJohn McCall Builder.CreateUnreachable(); 1560d88ea5687968640ada2bc5a10211cbeb68a671ecMike Stump 1561f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Restore the saved insertion state. 1562f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.restoreIP(SavedIP); 1563891f80ec2fb2d1730b769467d602689e1080845bJohn McCall 1564f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall return TerminateLandingPad; 1565d88ea5687968640ada2bc5a10211cbeb68a671ecMike Stump} 15669b39c51ae3c547568ac42325f94b4197618f6b18Mike Stump 15679b39c51ae3c547568ac42325f94b4197618f6b18Mike Stumpllvm::BasicBlock *CodeGenFunction::getTerminateHandler() { 1568182f383db1782af752ecaf607fdff72a8542088bMike Stump if (TerminateHandler) 1569182f383db1782af752ecaf607fdff72a8542088bMike Stump return TerminateHandler; 1570182f383db1782af752ecaf607fdff72a8542088bMike Stump 1571f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall CGBuilderTy::InsertPoint SavedIP = Builder.saveAndClearIP(); 15729b39c51ae3c547568ac42325f94b4197618f6b18Mike Stump 1573f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // Set up the terminate handler. This block is inserted at the very 1574f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall // end of the function by FinishFunction. 1575182f383db1782af752ecaf607fdff72a8542088bMike Stump TerminateHandler = createBasicBlock("terminate.handler"); 1576f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.SetInsertPoint(TerminateHandler); 157745ff3807ef06bca715afb9eb7e16c4c89880e40eJohn McCall llvm::CallInst *terminateCall; 157845ff3807ef06bca715afb9eb7e16c4c89880e40eJohn McCall if (useClangCallTerminate(CGM)) { 157945ff3807ef06bca715afb9eb7e16c4c89880e40eJohn McCall // Load the exception pointer. 158045ff3807ef06bca715afb9eb7e16c4c89880e40eJohn McCall llvm::Value *exn = getExceptionFromSlot(); 158145ff3807ef06bca715afb9eb7e16c4c89880e40eJohn McCall terminateCall = EmitNounwindRuntimeCall(getClangCallTerminateFn(CGM), exn); 158245ff3807ef06bca715afb9eb7e16c4c89880e40eJohn McCall } else { 158345ff3807ef06bca715afb9eb7e16c4c89880e40eJohn McCall terminateCall = EmitNounwindRuntimeCall(getTerminateFn(CGM)); 158445ff3807ef06bca715afb9eb7e16c4c89880e40eJohn McCall } 158545ff3807ef06bca715afb9eb7e16c4c89880e40eJohn McCall terminateCall->setDoesNotReturn(); 15869b39c51ae3c547568ac42325f94b4197618f6b18Mike Stump Builder.CreateUnreachable(); 15879b39c51ae3c547568ac42325f94b4197618f6b18Mike Stump 15883d3ec1c099ec8bfac3aa1fb0126fe515b7c7fa05John McCall // Restore the saved insertion state. 1589f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall Builder.restoreIP(SavedIP); 159076958099828bac6ebd45abef9f76934b3e99e397Mike Stump 15919b39c51ae3c547568ac42325f94b4197618f6b18Mike Stump return TerminateHandler; 15929b39c51ae3c547568ac42325f94b4197618f6b18Mike Stump} 1593f1549f66a8216a78112286e3978cea2c29d6334cJohn McCall 1594c686004145b1f4dbeb38173a0886ba7040ae0089David Chisnallllvm::BasicBlock *CodeGenFunction::getEHResumeBlock(bool isCleanup) { 1595777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall if (EHResumeBlock) return EHResumeBlock; 1596ff8e11579fc904aa4032d90d2be6ce1ac5fc9fe1John McCall 1597ff8e11579fc904aa4032d90d2be6ce1ac5fc9fe1John McCall CGBuilderTy::InsertPoint SavedIP = Builder.saveIP(); 1598ff8e11579fc904aa4032d90d2be6ce1ac5fc9fe1John McCall 1599ff8e11579fc904aa4032d90d2be6ce1ac5fc9fe1John McCall // We emit a jump to a notional label at the outermost unwind state. 1600777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall EHResumeBlock = createBasicBlock("eh.resume"); 1601777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall Builder.SetInsertPoint(EHResumeBlock); 1602ff8e11579fc904aa4032d90d2be6ce1ac5fc9fe1John McCall 16034e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie const EHPersonality &Personality = EHPersonality::get(CGM.getLangOpts()); 1604ff8e11579fc904aa4032d90d2be6ce1ac5fc9fe1John McCall 1605ff8e11579fc904aa4032d90d2be6ce1ac5fc9fe1John McCall // This can always be a call because we necessarily didn't find 1606ff8e11579fc904aa4032d90d2be6ce1ac5fc9fe1John McCall // anything on the EH stack which needs our help. 1607af2771b147f1a5934c6c91574f1c2df986034e74Benjamin Kramer const char *RethrowName = Personality.CatchallRethrowFn; 16086bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89Stephen Hines if (RethrowName != nullptr && !isCleanup) { 1609bd7370a78604e9a20d698bfe328c1e43f12a0613John McCall EmitRuntimeCall(getCatchallRethrowFn(CGM, RethrowName), 1610ef8225444452a1486bd721f3285301fe84643b00Stephen Hines getExceptionFromSlot()) 161193c332a8ba2c193c435b293966d343dab15f555bJohn McCall ->setDoesNotReturn(); 1612ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Builder.CreateUnreachable(); 1613ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Builder.restoreIP(SavedIP); 1614ef8225444452a1486bd721f3285301fe84643b00Stephen Hines return EHResumeBlock; 161593c332a8ba2c193c435b293966d343dab15f555bJohn McCall } 1616ff8e11579fc904aa4032d90d2be6ce1ac5fc9fe1John McCall 1617ef8225444452a1486bd721f3285301fe84643b00Stephen Hines // Recreate the landingpad's return value for the 'resume' instruction. 1618ef8225444452a1486bd721f3285301fe84643b00Stephen Hines llvm::Value *Exn = getExceptionFromSlot(); 1619ef8225444452a1486bd721f3285301fe84643b00Stephen Hines llvm::Value *Sel = getSelectorFromSlot(); 1620ff8e11579fc904aa4032d90d2be6ce1ac5fc9fe1John McCall 1621ef8225444452a1486bd721f3285301fe84643b00Stephen Hines llvm::Type *LPadType = llvm::StructType::get(Exn->getType(), 1622ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Sel->getType(), NULL); 1623ef8225444452a1486bd721f3285301fe84643b00Stephen Hines llvm::Value *LPadVal = llvm::UndefValue::get(LPadType); 1624ef8225444452a1486bd721f3285301fe84643b00Stephen Hines LPadVal = Builder.CreateInsertValue(LPadVal, Exn, 0, "lpad.val"); 1625ef8225444452a1486bd721f3285301fe84643b00Stephen Hines LPadVal = Builder.CreateInsertValue(LPadVal, Sel, 1, "lpad.val"); 1626ff8e11579fc904aa4032d90d2be6ce1ac5fc9fe1John McCall 1627ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Builder.CreateResume(LPadVal); 1628ef8225444452a1486bd721f3285301fe84643b00Stephen Hines Builder.restoreIP(SavedIP); 1629777d6e56ad9b1fed9866daf3ee6486d85c5b7d32John McCall return EHResumeBlock; 1630ff8e11579fc904aa4032d90d2be6ce1ac5fc9fe1John McCall} 163198592d9c4dff79480fdc25b83988de03f912b647Reid Kleckner 163298592d9c4dff79480fdc25b83988de03f912b647Reid Klecknervoid CodeGenFunction::EmitSEHTryStmt(const SEHTryStmt &S) { 163398592d9c4dff79480fdc25b83988de03f912b647Reid Kleckner CGM.ErrorUnsupported(&S, "SEH __try"); 163498592d9c4dff79480fdc25b83988de03f912b647Reid Kleckner} 1635ef8225444452a1486bd721f3285301fe84643b00Stephen Hines 1636ef8225444452a1486bd721f3285301fe84643b00Stephen Hinesvoid CodeGenFunction::EmitSEHLeaveStmt(const SEHLeaveStmt &S) { 1637ef8225444452a1486bd721f3285301fe84643b00Stephen Hines CGM.ErrorUnsupported(&S, "SEH __leave"); 1638ef8225444452a1486bd721f3285301fe84643b00Stephen Hines} 1639