clang 23.0.0git
CIRGenException.cpp
Go to the documentation of this file.
1//===--- CIRGenException.cpp - Emit CIR Code for C++ exceptions -*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This contains code dealing with C++ exception related code generation.
10//
11//===----------------------------------------------------------------------===//
12
13#include "CIRGenCXXABI.h"
14#include "CIRGenFunction.h"
15#include "mlir/IR/Block.h"
16#include "mlir/IR/Location.h"
17
19#include "llvm/Support/SaveAndRestore.h"
20
21using namespace clang;
22using namespace clang::CIRGen;
23
24const EHPersonality EHPersonality::GNU_C = {"__gcc_personality_v0", nullptr};
25const EHPersonality EHPersonality::GNU_C_SJLJ = {"__gcc_personality_sj0",
26 nullptr};
27const EHPersonality EHPersonality::GNU_C_SEH = {"__gcc_personality_seh0",
28 nullptr};
29const EHPersonality EHPersonality::NeXT_ObjC = {"__objc_personality_v0",
30 nullptr};
31const EHPersonality EHPersonality::GNU_CPlusPlus = {"__gxx_personality_v0",
32 nullptr};
34 "__gxx_personality_sj0", nullptr};
36 "__gxx_personality_seh0", nullptr};
37const EHPersonality EHPersonality::GNU_ObjC = {"__gnu_objc_personality_v0",
38 "objc_exception_throw"};
40 "__gnu_objc_personality_sj0", "objc_exception_throw"};
42 "__gnu_objc_personality_seh0", "objc_exception_throw"};
44 "__gnustep_objcxx_personality_v0", nullptr};
46 "__gnustep_objc_personality_v0", nullptr};
47const EHPersonality EHPersonality::MSVC_except_handler = {"_except_handler3",
48 nullptr};
50 "__C_specific_handler", nullptr};
52 "__CxxFrameHandler3", nullptr};
54 "__gxx_wasm_personality_v0", nullptr};
55const EHPersonality EHPersonality::XL_CPlusPlus = {"__xlcxx_personality_v1",
56 nullptr};
57const EHPersonality EHPersonality::ZOS_CPlusPlus = {"__zos_cxx_personality_v2",
58 nullptr};
59
60static const EHPersonality &getCPersonality(const TargetInfo &target,
61 const CodeGenOptions &cgOpts) {
62 const llvm::Triple &triple = target.getTriple();
63 if (triple.isWindowsMSVCEnvironment())
65 if (cgOpts.hasSjLjExceptions())
67 if (cgOpts.hasDWARFExceptions())
69 if (cgOpts.hasSEHExceptions())
72}
73
74static const EHPersonality &getObjCPersonality(const TargetInfo &target,
75 const LangOptions &langOpts,
76 const CodeGenOptions &cgOpts) {
77 const llvm::Triple &triple = target.getTriple();
78 if (triple.isWindowsMSVCEnvironment())
80
81 switch (langOpts.ObjCRuntime.getKind()) {
83 return getCPersonality(target, cgOpts);
89 if (langOpts.ObjCRuntime.getVersion() >= VersionTuple(1, 7))
91 [[fallthrough]];
94 if (cgOpts.hasSjLjExceptions())
96 if (cgOpts.hasSEHExceptions())
99 }
100 llvm_unreachable("bad runtime kind");
101}
102
103static const EHPersonality &getCXXPersonality(const TargetInfo &target,
104 const CodeGenOptions &cgOpts) {
105 const llvm::Triple &triple = target.getTriple();
106 if (triple.isWindowsMSVCEnvironment())
108 if (triple.isOSAIX())
110 if (cgOpts.hasSjLjExceptions())
112 if (cgOpts.hasDWARFExceptions())
114 if (cgOpts.hasSEHExceptions())
116 if (cgOpts.hasWasmExceptions())
119}
120
121/// Determines the personality function to use when both C++
122/// and Objective-C exceptions are being caught.
124 const LangOptions &langOpts,
125 const CodeGenOptions &cgOpts) {
126 if (target.getTriple().isWindowsMSVCEnvironment())
128
129 switch (langOpts.ObjCRuntime.getKind()) {
130 // In the fragile ABI, just use C++ exception handling and hope
131 // they're not doing crazy exception mixing.
133 return getCXXPersonality(target, cgOpts);
134
135 // The ObjC personality defers to the C++ personality for non-ObjC
136 // handlers. Unlike the C++ case, we use the same personality
137 // function on targets using (backend-driven) SJLJ EH.
139 case ObjCRuntime::iOS:
141 return getObjCPersonality(target, langOpts, cgOpts);
142
145
146 // The GCC runtime's personality function inherently doesn't support
147 // mixed EH. Use the ObjC personality just to avoid returning null.
148 case ObjCRuntime::GCC:
150 return getObjCPersonality(target, langOpts, cgOpts);
151 }
152 llvm_unreachable("bad runtime kind");
153}
154
155static const EHPersonality &getSEHPersonalityMSVC(const llvm::Triple &triple) {
156 return triple.getArch() == llvm::Triple::x86
159}
160
162 const FunctionDecl *fd) {
163 const llvm::Triple &triple = cgm.getTarget().getTriple();
164 const LangOptions &langOpts = cgm.getLangOpts();
165 const CodeGenOptions &cgOpts = cgm.getCodeGenOpts();
166 const TargetInfo &target = cgm.getTarget();
167
168 // Functions using SEH get an SEH personality.
169 if (fd && fd->usesSEHTry())
170 return getSEHPersonalityMSVC(triple);
171
172 if (langOpts.ObjC) {
173 return langOpts.CPlusPlus ? getObjCXXPersonality(target, langOpts, cgOpts)
174 : getObjCPersonality(target, langOpts, cgOpts);
175 }
176 return langOpts.CPlusPlus ? getCXXPersonality(target, cgOpts)
177 : getCPersonality(target, cgOpts);
178}
179
181 const auto *fg = cgf.curCodeDecl;
182 // For outlined finallys and filters, use the SEH personality in case they
183 // contain more SEH. This mostly only affects finallys. Filters could
184 // hypothetically use gnu statement expressions to sneak in nested SEH.
185 fg = fg ? fg : cgf.curSEHParent.getDecl();
186 return get(cgf.cgm, dyn_cast_or_null<FunctionDecl>(fg));
187}
188
189static llvm::StringRef getPersonalityFn(CIRGenModule &cgm,
190 const EHPersonality &personality) {
191 // Create the personality function type: i32 (...)
192 mlir::Type i32Ty = cgm.getBuilder().getI32Type();
193 auto funcTy = cir::FuncType::get({}, i32Ty, /*isVarArg=*/true);
194
195 cir::FuncOp personalityFn = cgm.createRuntimeFunction(
196 funcTy, personality.personalityFn, {}, /*isLocal=*/true);
197
198 return personalityFn.getSymName();
199}
200
202 const llvm::Triple &triple = getTarget().getTriple();
203 if (cgm.getLangOpts().OpenMPIsTargetDevice &&
204 (triple.isNVPTX() || triple.isAMDGCN())) {
205 cgm.errorNYI("emitCXXThrowExpr OpenMP with NVPTX or AMDGCN Triples");
206 return;
207 }
208
209 if (const Expr *subExpr = e->getSubExpr()) {
210 QualType throwType = subExpr->getType();
211 if (throwType->isObjCObjectPointerType()) {
212 cgm.errorNYI("emitCXXThrowExpr ObjCObjectPointerType");
213 return;
214 }
215
216 cgm.getCXXABI().emitThrow(*this, e);
217 return;
218 }
219
220 cgm.getCXXABI().emitRethrow(*this, /*isNoReturn=*/true);
221}
222
224 // Make sure the exception object is cleaned up if there's an
225 // exception during initialization.
227
228 // __cxa_allocate_exception returns a void*; we need to cast this
229 // to the appropriate type for the object.
230 mlir::Type ty = convertTypeForMem(e->getType());
231 Address typedAddr = addr.withElementType(builder, ty);
232
233 // From LLVM's codegen:
234 // FIXME: this isn't quite right! If there's a final unelided call
235 // to a copy constructor, then according to [except.terminate]p1 we
236 // must call std::terminate() if that constructor throws, because
237 // technically that copy occurs after the exception expression is
238 // evaluated but before the exception is caught. But the best way
239 // to handle that is to teach EmitAggExpr to do the final copy
240 // differently if it can't be elided.
241 emitAnyExprToMem(e, typedAddr, e->getType().getQualifiers(),
242 /*isInitializer=*/true);
243
244 // Deactivate the cleanup block.
246}
247
249 const CXXCatchStmt *catchStmt, SmallVector<mlir::Attribute> &handlerAttrs) {
250 mlir::Location catchLoc = getLoc(catchStmt->getBeginLoc());
251
252 if (catchStmt->getExceptionDecl()) {
253 // FIXME: Dropping the reference type on the type into makes it
254 // impossible to correctly implement catch-by-reference
255 // semantics for pointers. Unfortunately, this is what all
256 // existing compilers do, and it's not clear that the standard
257 // personality routine is capable of doing this right. See C++ DR 388:
258 // http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#388
259 Qualifiers caughtTypeQuals;
260 QualType caughtType = cgm.getASTContext().getUnqualifiedArrayType(
261 catchStmt->getCaughtType().getNonReferenceType(), caughtTypeQuals);
262 if (caughtType->isObjCObjectPointerType()) {
263 cgm.errorNYI("addCatchHandlerAttr: caughtType ObjCObjectPointerType");
264 return;
265 }
266
267 CatchTypeInfo typeInfo = cgm.getCXXABI().getAddrOfCXXCatchHandlerType(
268 catchLoc, caughtType, catchStmt->getCaughtType());
269 handlerAttrs.push_back(typeInfo.rtti);
270 } else {
271 // No exception decl indicates '...', a catch-all.
272 handlerAttrs.push_back(cir::CatchAllAttr::get(&getMLIRContext()));
273 }
274}
275
276mlir::LogicalResult
278 cxxTryBodyEmitter &bodyCallback) {
279 mlir::Location loc = getLoc(s.getSourceRange());
280
281 // Create a scope to hold try local storage for catch params.
282 mlir::OpBuilder::InsertPoint scopeIP;
283 cir::ScopeOp::create(
284 builder, loc,
285 /*scopeBuilder=*/[&](mlir::OpBuilder &b, mlir::Location loc) {
286 scopeIP = builder.saveInsertionPoint();
287 });
288
289 // Set personality function if not already set
290 auto funcOp = mlir::cast<cir::FuncOp>(curFn);
291 if (!funcOp.getPersonality())
292 funcOp.setPersonality(getPersonalityFn(cgm, EHPersonality::get(*this)));
293
294 mlir::OpBuilder::InsertionGuard guard(builder);
295 builder.restoreInsertionPoint(scopeIP);
296
297 const llvm::Triple &t = getTarget().getTriple();
298 // If we encounter a try statement on in an OpenMP target region offloaded to
299 // a GPU, we treat it as a basic block.
300 const bool isTargetDevice =
301 (cgm.getLangOpts().OpenMPIsTargetDevice && (t.isNVPTX() || t.isAMDGCN()));
302 if (isTargetDevice) {
303 cgm.errorNYI("emitCXXTryStmt: OpenMP target region offloaded to GPU");
304 return mlir::success();
305 }
306
307 mlir::Location tryLoc = getLoc(s.getBeginLoc());
308 SmallVector<mlir::Attribute> handlerAttrs;
309
310 CIRGenFunction::LexicalScope tryBodyScope{*this, tryLoc,
311 builder.getInsertionBlock()};
312
313 if (getLangOpts().EHAsynch) {
314 cgm.errorNYI("enterCXXTryStmt: EHAsynch");
315 return mlir::failure();
316 }
317
318 // Create the try operation.
319 mlir::LogicalResult tryRes = mlir::success();
320 auto tryOp = cir::TryOp::create(
321 builder, tryLoc,
322 /*tryBuilder=*/
323 [&](mlir::OpBuilder &b, mlir::Location loc) {
324 // Create a RunCleanupsScope that allows us to apply any cleanups that
325 // are created for statements within the try body before exiting the
326 // try body.
327 RunCleanupsScope tryBodyCleanups(*this);
328 if (bodyCallback(*this).failed())
329 tryRes = mlir::failure();
330 tryBodyCleanups.forceCleanup();
331 cir::YieldOp::create(builder, loc);
332 },
333 /*handlersBuilder=*/
334 [&](mlir::OpBuilder &b, mlir::Location loc,
335 mlir::OperationState &result) {
336 mlir::OpBuilder::InsertionGuard guard(b);
337 bool hasCatchAll = false;
338 unsigned numHandlers = s.getNumHandlers();
339 mlir::Type ehTokenTy = cir::EhTokenType::get(&getMLIRContext());
340 for (unsigned i = 0; i != numHandlers; ++i) {
341 const CXXCatchStmt *catchStmt = s.getHandler(i);
342 if (!catchStmt->getExceptionDecl())
343 hasCatchAll = true;
344 mlir::Region *region = result.addRegion();
345 builder.createBlock(region, /*insertPt=*/{}, {ehTokenTy}, {loc});
346 addCatchHandlerAttr(catchStmt, handlerAttrs);
347 }
348 if (!hasCatchAll) {
349 // Create unwind region.
350 mlir::Region *region = result.addRegion();
351 mlir::Block *unwindBlock =
352 builder.createBlock(region, /*insertPt=*/{}, {ehTokenTy}, {loc});
353 cir::ResumeOp::create(builder, loc, unwindBlock->getArgument(0));
354 handlerAttrs.push_back(cir::UnwindAttr::get(&getMLIRContext()));
355 }
356 });
357
358 if (tryRes.failed())
359 return mlir::failure();
360
361 // Add final array of clauses into TryOp.
362 tryOp.setHandlerTypesAttr(
363 mlir::ArrayAttr::get(&getMLIRContext(), handlerAttrs));
364
365 // Emit the catch handler bodies. This has to be done after the try op is
366 // created and in place so that we can find the insertion point for the
367 // catch parameter alloca.
368 unsigned numHandlers = s.getNumHandlers();
369 for (unsigned i = 0; i != numHandlers; ++i) {
370 const CXXCatchStmt *catchStmt = s.getHandler(i);
371 mlir::Region *handler = &tryOp.getHandlerRegions()[i];
372 mlir::Location handlerLoc = getLoc(catchStmt->getCatchLoc());
373
374 mlir::OpBuilder::InsertionGuard guard(builder);
375 builder.setInsertionPointToStart(&handler->front());
376
377 // Get the !cir.eh_token block argument from the handler region.
378 mlir::Value ehToken = handler->front().getArgument(0);
379
380 // Enter a cleanup scope, including the catch variable and the
381 // end-catch.
382 RunCleanupsScope handlerScope(*this);
383
384 // Initialize the catch variable.
385 // TODO(cir): Move this out of CXXABI.
387 cgm.getCXXABI().emitBeginCatch(*this, catchStmt, ehToken);
388
389 // Emit the PGO counter increment.
391
392 // Perform the body of the catch.
393 [[maybe_unused]] mlir::LogicalResult emitResult =
394 emitStmt(catchStmt->getHandlerBlock(), /*useCurrentScope=*/true);
395 assert(emitResult.succeeded() && "failed to emit catch handler block");
396
397 // [except.handle]p11:
398 // The currently handled exception is rethrown if control
399 // reaches the end of a handler of the function-try-block of a
400 // constructor or destructor.
401
402 // TODO(cir): Handle implicit rethrow?
403
404 // Fall out through the catch cleanups.
405 handlerScope.forceCleanup();
406
407 mlir::Block *block = &handler->getBlocks().back();
408 if (block->empty() ||
409 !block->back().hasTrait<mlir::OpTrait::IsTerminator>()) {
410 mlir::OpBuilder::InsertionGuard guard(builder);
411 builder.setInsertionPointToEnd(block);
412 builder.createYield(handlerLoc);
413 }
414 }
415
416 return mlir::success();
417}
418
419mlir::LogicalResult CIRGenFunction::emitCXXTryStmt(const CXXTryStmt &s) {
420 if (s.getTryBlock()->body_empty())
421 return mlir::LogicalResult::success();
422
423 struct simpleTryBodyEmitter final : cxxTryBodyEmitter {
424 const clang::CXXTryStmt &s;
425 simpleTryBodyEmitter(const clang::CXXTryStmt &s) : s(s) {}
426
427 mlir::LogicalResult operator()(CIRGenFunction &cgf) override {
428 return cgf.emitStmt(s.getTryBlock(), /*useCurrentScope=*/true);
429 }
430 ~simpleTryBodyEmitter() override = default;
431 };
432
433 simpleTryBodyEmitter emitter{s};
434
435 return emitCXXTryStmt(s, emitter);
436}
437
438// in classic codegen this function is mapping to `isInvokeDest` previously and
439// currently it's mapping to the conditions that performs early returns in
440// `getInvokeDestImpl`, in CIR we need the condition to know if the EH scope may
441// throw exception or now.
443 // If exceptions are disabled/ignored and SEH is not in use, then there is no
444 // invoke destination. SEH "works" even if exceptions are off. In practice,
445 // this means that C++ destructors and other EH cleanups don't run, which is
446 // consistent with MSVC's behavior, except in the presence of -EHa
447 const LangOptions &lo = cgm.getLangOpts();
448 if (!lo.Exceptions || lo.IgnoreExceptions) {
449 if (!lo.Borland && !lo.MicrosoftExt)
450 return false;
451 cgm.errorNYI("isInvokeDest: no exceptions or ignore exception");
452 return false;
453 }
454
455 // CUDA device code doesn't have exceptions.
456 if (lo.CUDA && lo.CUDAIsDevice)
457 return false;
458
459 return ehStack.requiresCatchOrCleanup();
460}
static const EHPersonality & getCXXPersonality(const TargetInfo &target, const CodeGenOptions &cgOpts)
static const EHPersonality & getCPersonality(const TargetInfo &target, const CodeGenOptions &cgOpts)
static const EHPersonality & getObjCPersonality(const TargetInfo &target, const LangOptions &langOpts, const CodeGenOptions &cgOpts)
static llvm::StringRef getPersonalityFn(CIRGenModule &cgm, const EHPersonality &personality)
static const EHPersonality & getObjCXXPersonality(const TargetInfo &target, const LangOptions &langOpts, const CodeGenOptions &cgOpts)
Determines the personality function to use when both C++ and Objective-C exceptions are being caught.
static const EHPersonality & getSEHPersonalityMSVC(const llvm::Triple &triple)
__device__ __2f16 b
__device__ __2f16 float __ockl_bool s
Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const
Return address with different element type, a bitcast pointer, and the same alignment.
Enters a new scope for capturing cleanups, all of which will be executed once the scope is exited.
void forceCleanup(ArrayRef< mlir::Value * > valuesToReload={})
Force the emission of cleanups now, instead of waiting until this object is destroyed.
const clang::LangOptions & getLangOpts() const
const TargetInfo & getTarget() const
void addCatchHandlerAttr(const CXXCatchStmt *catchStmt, SmallVector< mlir::Attribute > &handlerAttrs)
void emitAnyExprToExn(const Expr *e, Address addr)
mlir::Location getLoc(clang::SourceLocation srcLoc)
Helpers to convert Clang's SourceLocation to a MLIR Location.
void emitAnyExprToMem(const Expr *e, Address location, Qualifiers quals, bool isInitializer)
Emits the code necessary to evaluate an arbitrary expression into the given memory location.
mlir::Operation * curFn
The current function or global initializer that is generated code for.
EHScopeStack ehStack
Tracks function scope overall cleanup handling.
mlir::Type convertTypeForMem(QualType t)
mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s, cxxTryBodyEmitter &bodyCallback)
const clang::Decl * curCodeDecl
This is the inner-most code context, which includes blocks.
mlir::MLIRContext & getMLIRContext()
void emitCXXThrowExpr(const CXXThrowExpr *e)
CIRGenFunction(CIRGenModule &cgm, CIRGenBuilderTy &builder, bool suppressNewContext=false)
mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope, llvm::ArrayRef< const Attr * > attrs={})
This class organizes the cross-function state that is used while generating CIR code.
CIRGenBuilderTy & getBuilder()
const clang::TargetInfo & getTarget() const
cir::FuncOp createRuntimeFunction(cir::FuncType ty, llvm::StringRef name, mlir::NamedAttrList extraAttrs={}, bool isLocal=false, bool assumeConvergent=false)
const clang::CodeGenOptions & getCodeGenOpts() const
const clang::LangOptions & getLangOpts() const
CXXCatchStmt - This represents a C++ catch block.
Definition StmtCXX.h:28
SourceLocation getCatchLoc() const
Definition StmtCXX.h:48
Stmt * getHandlerBlock() const
Definition StmtCXX.h:51
SourceLocation getBeginLoc() const LLVM_READONLY
Definition StmtCXX.h:43
VarDecl * getExceptionDecl() const
Definition StmtCXX.h:49
QualType getCaughtType() const
Definition StmtCXX.cpp:19
A C++ throw-expression (C++ [except.throw]).
Definition ExprCXX.h:1209
const Expr * getSubExpr() const
Definition ExprCXX.h:1229
CXXTryStmt - A C++ try block, including all handlers.
Definition StmtCXX.h:69
CodeGenOptions - Track various options which control how the code is optimized and passed to the back...
bool hasDWARFExceptions() const
bool hasWasmExceptions() const
bool hasSjLjExceptions() const
bool hasSEHExceptions() const
This represents one expression.
Definition Expr.h:112
QualType getType() const
Definition Expr.h:144
Represents a function declaration or definition.
Definition Decl.h:2015
bool usesSEHTry() const
Indicates the function uses __try.
Definition Decl.h:2533
const Decl * getDecl() const
Definition GlobalDecl.h:106
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
clang::ObjCRuntime ObjCRuntime
Kind getKind() const
Definition ObjCRuntime.h:77
const VersionTuple & getVersion() const
Definition ObjCRuntime.h:78
@ MacOSX
'macosx' is the Apple-provided NeXT-derived runtime on Mac OS X platforms that use the non-fragile AB...
Definition ObjCRuntime.h:35
@ FragileMacOSX
'macosx-fragile' is the Apple-provided NeXT-derived runtime on Mac OS X platforms that use the fragil...
Definition ObjCRuntime.h:40
@ GNUstep
'gnustep' is the modern non-fragile GNUstep runtime.
Definition ObjCRuntime.h:56
@ ObjFW
'objfw' is the Objective-C runtime included in ObjFW
Definition ObjCRuntime.h:59
@ iOS
'ios' is the Apple-provided NeXT-derived runtime on iOS or the iOS simulator; it is always non-fragil...
Definition ObjCRuntime.h:45
@ GCC
'gcc' is the Objective-C runtime shipped with GCC, implementing a fragile Objective-C ABI
Definition ObjCRuntime.h:53
@ WatchOS
'watchos' is a variant of iOS for Apple's watchOS.
Definition ObjCRuntime.h:49
A (possibly-)qualified type.
Definition TypeBase.h:937
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
Definition TypeBase.h:8471
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition TypeBase.h:8616
The collection of all-type qualifiers we support.
Definition TypeBase.h:331
Exposes information about the current target.
Definition TargetInfo.h:227
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
bool isObjCObjectPointerType() const
Definition TypeBase.h:8847
The JSON file list parser is used to communicate input to InstallAPI.
static bool ehCleanupScope()
static bool currentFuncletPad()
static bool incrementProfileCounter()
Represents a scope, including function bodies, compound statements, and the substatements of if/while...
The MS C++ ABI needs a pointer to RTTI data plus some flags to describe the type of a catch handler,...
The exceptions personality for a function.
static const EHPersonality XL_CPlusPlus
static const EHPersonality GNU_ObjC_SJLJ
static const EHPersonality ZOS_CPlusPlus
static const EHPersonality GNUstep_ObjC
static const EHPersonality MSVC_CxxFrameHandler3
static const EHPersonality MSVC_C_specific_handler
static const EHPersonality GNU_CPlusPlus_SEH
static const EHPersonality GNU_ObjC
static const EHPersonality GNU_CPlusPlus_SJLJ
static const EHPersonality GNU_C_SJLJ
static const EHPersonality GNU_C
static const EHPersonality NeXT_ObjC
static const EHPersonality & get(CIRGenModule &cgm, const clang::FunctionDecl *fd)
static const EHPersonality GNU_CPlusPlus
static const EHPersonality GNU_ObjCXX
static const EHPersonality GNU_C_SEH
static const EHPersonality MSVC_except_handler
static const EHPersonality GNU_ObjC_SEH
static const EHPersonality GNU_Wasm_CPlusPlus