clang 22.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
18#include "llvm/Support/SaveAndRestore.h"
19
20using namespace clang;
21using namespace clang::CIRGen;
22
23const EHPersonality EHPersonality::GNU_C = {"__gcc_personality_v0", nullptr};
24const EHPersonality EHPersonality::GNU_C_SJLJ = {"__gcc_personality_sj0",
25 nullptr};
26const EHPersonality EHPersonality::GNU_C_SEH = {"__gcc_personality_seh0",
27 nullptr};
28const EHPersonality EHPersonality::NeXT_ObjC = {"__objc_personality_v0",
29 nullptr};
30const EHPersonality EHPersonality::GNU_CPlusPlus = {"__gxx_personality_v0",
31 nullptr};
33 "__gxx_personality_sj0", nullptr};
35 "__gxx_personality_seh0", nullptr};
36const EHPersonality EHPersonality::GNU_ObjC = {"__gnu_objc_personality_v0",
37 "objc_exception_throw"};
39 "__gnu_objc_personality_sj0", "objc_exception_throw"};
41 "__gnu_objc_personality_seh0", "objc_exception_throw"};
43 "__gnustep_objcxx_personality_v0", nullptr};
45 "__gnustep_objc_personality_v0", nullptr};
46const EHPersonality EHPersonality::MSVC_except_handler = {"_except_handler3",
47 nullptr};
49 "__C_specific_handler", nullptr};
51 "__CxxFrameHandler3", nullptr};
53 "__gxx_wasm_personality_v0", nullptr};
54const EHPersonality EHPersonality::XL_CPlusPlus = {"__xlcxx_personality_v1",
55 nullptr};
56const EHPersonality EHPersonality::ZOS_CPlusPlus = {"__zos_cxx_personality_v2",
57 nullptr};
58
59static const EHPersonality &getCPersonality(const TargetInfo &target,
60 const CodeGenOptions &cgOpts) {
61 const llvm::Triple &triple = target.getTriple();
62 if (triple.isWindowsMSVCEnvironment())
64 if (cgOpts.hasSjLjExceptions())
66 if (cgOpts.hasDWARFExceptions())
68 if (cgOpts.hasSEHExceptions())
71}
72
73static const EHPersonality &getObjCPersonality(const TargetInfo &target,
74 const LangOptions &langOpts,
75 const CodeGenOptions &cgOpts) {
76 const llvm::Triple &triple = target.getTriple();
77 if (triple.isWindowsMSVCEnvironment())
79
80 switch (langOpts.ObjCRuntime.getKind()) {
82 return getCPersonality(target, cgOpts);
88 if (langOpts.ObjCRuntime.getVersion() >= VersionTuple(1, 7))
90 [[fallthrough]];
93 if (cgOpts.hasSjLjExceptions())
95 if (cgOpts.hasSEHExceptions())
98 }
99 llvm_unreachable("bad runtime kind");
100}
101
102static const EHPersonality &getCXXPersonality(const TargetInfo &target,
103 const CodeGenOptions &cgOpts) {
104 const llvm::Triple &triple = target.getTriple();
105 if (triple.isWindowsMSVCEnvironment())
107 if (triple.isOSAIX())
109 if (cgOpts.hasSjLjExceptions())
111 if (cgOpts.hasDWARFExceptions())
113 if (cgOpts.hasSEHExceptions())
115 if (cgOpts.hasWasmExceptions())
118}
119
120/// Determines the personality function to use when both C++
121/// and Objective-C exceptions are being caught.
123 const LangOptions &langOpts,
124 const CodeGenOptions &cgOpts) {
125 if (target.getTriple().isWindowsMSVCEnvironment())
127
128 switch (langOpts.ObjCRuntime.getKind()) {
129 // In the fragile ABI, just use C++ exception handling and hope
130 // they're not doing crazy exception mixing.
132 return getCXXPersonality(target, cgOpts);
133
134 // The ObjC personality defers to the C++ personality for non-ObjC
135 // handlers. Unlike the C++ case, we use the same personality
136 // function on targets using (backend-driven) SJLJ EH.
138 case ObjCRuntime::iOS:
140 return getObjCPersonality(target, langOpts, cgOpts);
141
144
145 // The GCC runtime's personality function inherently doesn't support
146 // mixed EH. Use the ObjC personality just to avoid returning null.
147 case ObjCRuntime::GCC:
149 return getObjCPersonality(target, langOpts, cgOpts);
150 }
151 llvm_unreachable("bad runtime kind");
152}
153
154static const EHPersonality &getSEHPersonalityMSVC(const llvm::Triple &triple) {
155 return triple.getArch() == llvm::Triple::x86
158}
159
161 const FunctionDecl *fd) {
162 const llvm::Triple &triple = cgm.getTarget().getTriple();
163 const LangOptions &langOpts = cgm.getLangOpts();
164 const CodeGenOptions &cgOpts = cgm.getCodeGenOpts();
165 const TargetInfo &target = cgm.getTarget();
166
167 // Functions using SEH get an SEH personality.
168 if (fd && fd->usesSEHTry())
169 return getSEHPersonalityMSVC(triple);
170
171 if (langOpts.ObjC) {
172 return langOpts.CPlusPlus ? getObjCXXPersonality(target, langOpts, cgOpts)
173 : getObjCPersonality(target, langOpts, cgOpts);
174 }
175 return langOpts.CPlusPlus ? getCXXPersonality(target, cgOpts)
176 : getCPersonality(target, cgOpts);
177}
178
180 const auto *fg = cgf.curCodeDecl;
181 // For outlined finallys and filters, use the SEH personality in case they
182 // contain more SEH. This mostly only affects finallys. Filters could
183 // hypothetically use gnu statement expressions to sneak in nested SEH.
184 fg = fg ? fg : cgf.curSEHParent.getDecl();
185 return get(cgf.cgm, dyn_cast_or_null<FunctionDecl>(fg));
186}
187
189 const llvm::Triple &triple = getTarget().getTriple();
190 if (cgm.getLangOpts().OpenMPIsTargetDevice &&
191 (triple.isNVPTX() || triple.isAMDGCN())) {
192 cgm.errorNYI("emitCXXThrowExpr OpenMP with NVPTX or AMDGCN Triples");
193 return;
194 }
195
196 if (const Expr *subExpr = e->getSubExpr()) {
197 QualType throwType = subExpr->getType();
198 if (throwType->isObjCObjectPointerType()) {
199 cgm.errorNYI("emitCXXThrowExpr ObjCObjectPointerType");
200 return;
201 }
202
203 cgm.getCXXABI().emitThrow(*this, e);
204 return;
205 }
206
207 cgm.getCXXABI().emitRethrow(*this, /*isNoReturn=*/true);
208}
209
211 // Make sure the exception object is cleaned up if there's an
212 // exception during initialization.
214
215 // __cxa_allocate_exception returns a void*; we need to cast this
216 // to the appropriate type for the object.
217 mlir::Type ty = convertTypeForMem(e->getType());
218 Address typedAddr = addr.withElementType(builder, ty);
219
220 // From LLVM's codegen:
221 // FIXME: this isn't quite right! If there's a final unelided call
222 // to a copy constructor, then according to [except.terminate]p1 we
223 // must call std::terminate() if that constructor throws, because
224 // technically that copy occurs after the exception expression is
225 // evaluated but before the exception is caught. But the best way
226 // to handle that is to teach EmitAggExpr to do the final copy
227 // differently if it can't be elided.
228 emitAnyExprToMem(e, typedAddr, e->getType().getQualifiers(),
229 /*isInitializer=*/true);
230
231 // Deactivate the cleanup block.
233}
234
235mlir::LogicalResult CIRGenFunction::emitCXXTryStmt(const CXXTryStmt &s) {
236 if (s.getTryBlock()->body_empty())
237 return mlir::LogicalResult::success();
238
239 mlir::Location loc = getLoc(s.getSourceRange());
240 // Create a scope to hold try local storage for catch params.
241
242 mlir::OpBuilder::InsertPoint scopeIP;
243 cir::ScopeOp::create(
244 builder, loc,
245 /*scopeBuilder=*/[&](mlir::OpBuilder &b, mlir::Location loc) {
246 scopeIP = builder.saveInsertionPoint();
247 });
248
249 mlir::OpBuilder::InsertionGuard guard(builder);
250 builder.restoreInsertionPoint(scopeIP);
251 mlir::LogicalResult result = emitCXXTryStmtUnderScope(s);
252 cir::YieldOp::create(builder, loc);
253 return result;
254}
255
256mlir::LogicalResult
258 const llvm::Triple &t = getTarget().getTriple();
259 // If we encounter a try statement on in an OpenMP target region offloaded to
260 // a GPU, we treat it as a basic block.
261 const bool isTargetDevice =
262 (cgm.getLangOpts().OpenMPIsTargetDevice && (t.isNVPTX() || t.isAMDGCN()));
263 if (isTargetDevice) {
264 cgm.errorNYI(
265 "emitCXXTryStmtUnderScope: OpenMP target region offloaded to GPU");
266 return mlir::success();
267 }
268
269 unsigned numHandlers = s.getNumHandlers();
270 mlir::Location tryLoc = getLoc(s.getBeginLoc());
271 mlir::OpBuilder::InsertPoint beginInsertTryBody;
272
273 bool hasCatchAll = false;
274 for (unsigned i = 0; i != numHandlers; ++i) {
275 hasCatchAll |= s.getHandler(i)->getExceptionDecl() == nullptr;
276 if (hasCatchAll)
277 break;
278 }
279
280 // Create the scope to represent only the C/C++ `try {}` part. However,
281 // don't populate right away. Create regions for the catch handlers,
282 // but don't emit the handler bodies yet. For now, only make sure the
283 // scope returns the exception information.
284 auto tryOp = cir::TryOp::create(
285 builder, tryLoc,
286 /*tryBuilder=*/
287 [&](mlir::OpBuilder &b, mlir::Location loc) {
288 beginInsertTryBody = builder.saveInsertionPoint();
289 },
290 /*handlersBuilder=*/
291 [&](mlir::OpBuilder &b, mlir::Location loc,
292 mlir::OperationState &result) {
293 mlir::OpBuilder::InsertionGuard guard(b);
294
295 // We create an extra region for an unwind catch handler in case the
296 // catch-all handler doesn't exists
297 unsigned numRegionsToCreate =
298 hasCatchAll ? numHandlers : numHandlers + 1;
299
300 for (unsigned i = 0; i != numRegionsToCreate; ++i) {
301 mlir::Region *region = result.addRegion();
302 builder.createBlock(region);
303 }
304 });
305
306 // Finally emit the body for try/catch.
307 {
308 mlir::Location loc = tryOp.getLoc();
309 mlir::OpBuilder::InsertionGuard guard(builder);
310 builder.restoreInsertionPoint(beginInsertTryBody);
311 CIRGenFunction::LexicalScope tryScope{*this, loc,
312 builder.getInsertionBlock()};
313
314 tryScope.setAsTry(tryOp);
315
316 // Attach the basic blocks for the catch regions.
317 enterCXXTryStmt(s, tryOp);
318
319 // Emit the body for the `try {}` part.
320 {
321 mlir::OpBuilder::InsertionGuard guard(builder);
322 CIRGenFunction::LexicalScope tryBodyScope{*this, loc,
323 builder.getInsertionBlock()};
324 if (emitStmt(s.getTryBlock(), /*useCurrentScope=*/true).failed())
325 return mlir::failure();
326 }
327
328 // Emit catch clauses.
330 }
331
332 return mlir::success();
333}
334
335void CIRGenFunction::enterCXXTryStmt(const CXXTryStmt &s, cir::TryOp tryOp,
336 bool isFnTryBlock) {
337 unsigned numHandlers = s.getNumHandlers();
338 EHCatchScope *catchScope = ehStack.pushCatch(numHandlers);
339 for (unsigned i = 0; i != numHandlers; ++i) {
340 const CXXCatchStmt *catchStmt = s.getHandler(i);
341 if (catchStmt->getExceptionDecl()) {
342 cgm.errorNYI("enterCXXTryStmt: CatchStmt with ExceptionDecl");
343 return;
344 }
345
346 // No exception decl indicates '...', a catch-all.
347 mlir::Region *handler = &tryOp.getHandlerRegions()[i];
348 catchScope->setHandler(i, cgm.getCXXABI().getCatchAllTypeInfo(), handler,
349 s.getHandler(i));
350
351 // Under async exceptions, catch(...) needs to catch HW exception too
352 // Mark scope with SehTryBegin as a SEH __try scope
353 if (getLangOpts().EHAsynch) {
354 cgm.errorNYI("enterCXXTryStmt: EHAsynch");
355 return;
356 }
357 }
358}
359
360void CIRGenFunction::exitCXXTryStmt(const CXXTryStmt &s, bool isFnTryBlock) {
361 unsigned numHandlers = s.getNumHandlers();
362 EHCatchScope &catchScope = cast<EHCatchScope>(*ehStack.begin());
363 assert(catchScope.getNumHandlers() == numHandlers);
364 cir::TryOp tryOp = curLexScope->getTry();
365
366 // If the catch was not required, bail out now.
367 if (!catchScope.mayThrow()) {
368 catchScope.clearHandlerBlocks();
369 ehStack.popCatch();
370
371 // Drop all basic block from all catch regions.
372 SmallVector<mlir::Block *> eraseBlocks;
373 for (mlir::Region &handlerRegion : tryOp.getHandlerRegions()) {
374 if (handlerRegion.empty())
375 continue;
376
377 for (mlir::Block &b : handlerRegion.getBlocks())
378 eraseBlocks.push_back(&b);
379 }
380
381 for (mlir::Block *b : eraseBlocks)
382 b->erase();
383
384 tryOp.setHandlerTypesAttr({});
385 return;
386 }
387
388 // Copy the handler blocks off before we pop the EH stack. Emitting
389 // the handlers might scribble on this memory.
390 SmallVector<EHCatchScope::Handler> handlers(catchScope.begin(),
391 catchScope.begin() + numHandlers);
392
393 ehStack.popCatch();
394
395 // Determine if we need an implicit rethrow for all these catch handlers;
396 // see the comment below.
397 bool doImplicitRethrow =
399
400 // Wasm uses Windows-style EH instructions, but merges all catch clauses into
401 // one big catchpad. So we save the old funclet pad here before we traverse
402 // each catch handler.
403 if (EHPersonality::get(*this).isWasmPersonality()) {
404 cgm.errorNYI("exitCXXTryStmt: WASM personality");
405 return;
406 }
407
408 bool hasCatchAll = false;
409 for (auto &handler : llvm::reverse(handlers)) {
410 hasCatchAll |= handler.isCatchAll();
411 mlir::Region *catchRegion = handler.region;
412 const CXXCatchStmt *catchStmt = handler.stmt;
413
414 mlir::OpBuilder::InsertionGuard guard(builder);
415 builder.setInsertionPointToStart(&catchRegion->front());
416
417 // Enter a cleanup scope, including the catch variable and the
418 // end-catch.
419 RunCleanupsScope catchScope(*this);
420
421 // Initialize the catch variable and set up the cleanups.
423
424 // Emit the PGO counter increment.
426
427 // Perform the body of the catch.
428 [[maybe_unused]] mlir::LogicalResult emitResult =
429 emitStmt(catchStmt->getHandlerBlock(), /*useCurrentScope=*/true);
430 assert(emitResult.succeeded() && "failed to emit catch handler block");
431
433 cir::YieldOp::create(builder, tryOp->getLoc());
434
435 // [except.handle]p11:
436 // The currently handled exception is rethrown if control
437 // reaches the end of a handler of the function-try-block of a
438 // constructor or destructor.
439
440 // It is important that we only do this on fallthrough and not on
441 // return. Note that it's illegal to put a return in a
442 // constructor function-try-block's catch handler (p14), so this
443 // really only applies to destructors.
444 if (doImplicitRethrow) {
445 cgm.errorNYI("exitCXXTryStmt: doImplicitRethrow");
446 return;
447 }
448
449 // Fall out through the catch cleanups.
450 catchScope.forceCleanup();
451 }
452
453 // Because in wasm we merge all catch clauses into one big catchpad, in case
454 // none of the types in catch handlers matches after we test against each of
455 // them, we should unwind to the next EH enclosing scope. We generate a call
456 // to rethrow function here to do that.
457 if (EHPersonality::get(*this).isWasmPersonality() && !hasCatchAll) {
458 cgm.errorNYI("exitCXXTryStmt: WASM personality without catch all");
459 }
460
462}
463
465 assert(ehStack.requiresCatchOrCleanup());
466 assert(!cgm.getLangOpts().IgnoreExceptions &&
467 "LandingPad should not be emitted when -fignore-exceptions are in "
468 "effect.");
469
470 EHScope &innermostEHScope = *ehStack.find(ehStack.getInnermostEHScope());
471 switch (innermostEHScope.getKind()) {
473 cgm.errorNYI("populateCatchHandlers: terminate");
474 return;
475
476 case EHScope::Catch:
477 case EHScope::Cleanup:
478 case EHScope::Filter:
479 // CIR does not cache landing pads.
480 break;
481 }
482
483 // If there's an existing TryOp, it means we got a `cir.try` scope
484 // that leads to this "landing pad" creation site. Otherwise, exceptions
485 // are enabled but a throwing function is called anyways (common pattern
486 // with function local static initializers).
487 mlir::ArrayAttr handlerTypesAttr = tryOp.getHandlerTypesAttr();
488 if (!handlerTypesAttr || handlerTypesAttr.empty()) {
489 // Accumulate all the handlers in scope.
490 bool hasCatchAll = false;
492 for (EHScopeStack::iterator i = ehStack.begin(), e = ehStack.end(); i != e;
493 ++i) {
494 switch (i->getKind()) {
495 case EHScope::Cleanup:
496 cgm.errorNYI("emitLandingPad: Cleanup");
497 return;
498
499 case EHScope::Filter:
500 cgm.errorNYI("emitLandingPad: Filter");
501 return;
502
504 cgm.errorNYI("emitLandingPad: Terminate");
505 return;
506
507 case EHScope::Catch:
508 break;
509 } // end switch
510
511 EHCatchScope &catchScope = cast<EHCatchScope>(*i);
512 for (const EHCatchScope::Handler &handler :
513 llvm::make_range(catchScope.begin(), catchScope.end())) {
514 assert(handler.type.flags == 0 &&
515 "landingpads do not support catch handler flags");
516
517 // If this is a catch-all, register that and abort.
518 if (handler.isCatchAll()) {
519 assert(!hasCatchAll);
520 hasCatchAll = true;
521 break;
522 }
523
524 cgm.errorNYI("emitLandingPad: non catch-all");
525 return;
526 }
527
528 if (hasCatchAll)
529 break;
530 }
531
532 if (hasCatchAll) {
533 handlerAttrs.push_back(cir::CatchAllAttr::get(&getMLIRContext()));
534 } else {
535 cgm.errorNYI("emitLandingPad: non catch-all");
536 return;
537 }
538
539 // Add final array of clauses into TryOp.
540 tryOp.setHandlerTypesAttr(
541 mlir::ArrayAttr::get(&getMLIRContext(), handlerAttrs));
542 }
543
544 // In traditional LLVM codegen. this tells the backend how to generate the
545 // landing pad by generating a branch to the dispatch block. In CIR,
546 // this is used to populate blocks for later filing during
547 // cleanup handling.
548 populateEHCatchRegions(ehStack.getInnermostEHScope(), tryOp);
549}
550
551// Differently from LLVM traditional codegen, there are no dispatch blocks
552// to look at given cir.try_call does not jump to blocks like invoke does.
553// However.
555 cir::TryOp tryOp) {
556 if (EHPersonality::get(*this).usesFuncletPads()) {
557 cgm.errorNYI("getEHDispatchBlock: usesFuncletPads");
558 return;
559 }
560
561 // Otherwise, we should look at the actual scope.
562 EHScope &ehScope = *ehStack.find(scope);
563 bool mayThrow = ehScope.mayThrow();
564
565 mlir::Block *originalBlock = nullptr;
566 if (mayThrow && tryOp) {
567 // If the dispatch is cached but comes from a different tryOp, make sure:
568 // - Populate current `tryOp` with a new dispatch block regardless.
569 // - Update the map to enqueue new dispatchBlock to also get a cleanup. See
570 // code at the end of the function.
571 cgm.errorNYI("getEHDispatchBlock: mayThrow & tryOp");
572 return;
573 }
574
575 if (!mayThrow) {
576 switch (ehScope.getKind()) {
577 case EHScope::Catch: {
578 // LLVM does some optimization with branches here, CIR just keep track of
579 // the corresponding calls.
580 EHCatchScope &catchScope = cast<EHCatchScope>(ehScope);
581 if (catchScope.getNumHandlers() == 1 &&
582 catchScope.getHandler(0).isCatchAll()) {
583 mayThrow = true;
584 break;
585 }
586 cgm.errorNYI("getEHDispatchBlock: mayThrow non-catch all");
587 return;
588 }
589 case EHScope::Cleanup: {
590 cgm.errorNYI("getEHDispatchBlock: mayThrow & cleanup");
591 return;
592 }
593 case EHScope::Filter: {
594 cgm.errorNYI("getEHDispatchBlock: mayThrow & Filter");
595 return;
596 }
597 case EHScope::Terminate: {
598 cgm.errorNYI("getEHDispatchBlock: mayThrow & Terminate");
599 return;
600 }
601 }
602 }
603
604 if (originalBlock) {
605 cgm.errorNYI("getEHDispatchBlock: originalBlock");
606 return;
607 }
608
609 ehScope.setMayThrow(mayThrow);
610}
611
612// in classic codegen this function is mapping to `isInvokeDest` previously and
613// currently it's mapping to the conditions that performs early returns in
614// `getInvokeDestImpl`, in CIR we need the condition to know if the EH scope may
615// throw exception or now.
617 // If exceptions are disabled/ignored and SEH is not in use, then there is no
618 // invoke destination. SEH "works" even if exceptions are off. In practice,
619 // this means that C++ destructors and other EH cleanups don't run, which is
620 // consistent with MSVC's behavior, except in the presence of -EHa
621 const LangOptions &lo = cgm.getLangOpts();
622 if (!lo.Exceptions || lo.IgnoreExceptions) {
623 if (!lo.Borland && !lo.MicrosoftExt)
624 return false;
625 cgm.errorNYI("isInvokeDest: no exceptions or ignore exception");
626 return false;
627 }
628
629 // CUDA device code doesn't have exceptions.
630 if (lo.CUDA && lo.CUDAIsDevice)
631 return false;
632
633 return ehStack.requiresCatchOrCleanup();
634}
635
636// In classic codegen this function is equivalent to `getInvokeDestImpl`, in
637// ClangIR we don't need to return to return any landing pad, we just need to
638// populate the catch handlers if they are required
640 assert(ehStack.requiresCatchOrCleanup());
641 assert(!ehStack.empty());
642
644
645 // CIR does not cache landing pads.
646 const EHPersonality &personality = EHPersonality::get(*this);
647 if (personality.usesFuncletPads()) {
648 cgm.errorNYI("getInvokeDestImpl: usesFuncletPads");
649 } else {
651 }
652}
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 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()
Force the emission of cleanups now, instead of waiting until this object is destroyed.
const clang::LangOptions & getLangOpts() const
void enterCXXTryStmt(const CXXTryStmt &s, cir::TryOp tryOp, bool isFnTryBlock=false)
void populateEHCatchRegions(EHScopeStack::stable_iterator scope, cir::TryOp tryOp)
void exitCXXTryStmt(const CXXTryStmt &s, bool isFnTryBlock=false)
const TargetInfo & getTarget() const
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::LogicalResult emitCXXTryStmtUnderScope(const clang::CXXTryStmt &s)
EHScopeStack ehStack
Tracks function scope overall cleanup handling.
void populateCatchHandlersIfRequired(cir::TryOp tryOp)
mlir::Type convertTypeForMem(QualType t)
const clang::Decl * curCodeDecl
This is the inner-most code context, which includes blocks.
mlir::MLIRContext & getMLIRContext()
mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s)
void emitCXXThrowExpr(const CXXThrowExpr *e)
void populateCatchHandlers(cir::TryOp tryOp)
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.
const clang::TargetInfo & getTarget() const
const clang::CodeGenOptions & getCodeGenOpts() const
const clang::LangOptions & getLangOpts() const
A scope which attempts to handle some, possibly all, types of exceptions.
const Handler & getHandler(unsigned i) const
unsigned getNumHandlers() const
void setHandler(unsigned i, CatchTypeInfo type, mlir::Region *region, const CXXCatchStmt *stmt)
A non-stable pointer into the scope stack.
A saved depth on the scope stack.
A protected scope for zero-cost EH handling.
void setMayThrow(bool mayThrow)
CXXCatchStmt - This represents a C++ catch block.
Definition StmtCXX.h:28
Stmt * getHandlerBlock() const
Definition StmtCXX.h:51
VarDecl * getExceptionDecl() const
Definition StmtCXX.h:49
A C++ throw-expression (C++ [except.throw]).
Definition ExprCXX.h:1208
const Expr * getSubExpr() const
Definition ExprCXX.h:1228
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:2000
bool usesSEHTry() const
Indicates the function uses __try.
Definition Decl.h:2518
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:8318
Exposes information about the current target.
Definition TargetInfo.h:226
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
bool isObjCObjectPointerType() const
Definition TypeBase.h:8684
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
Definition Address.h:330
U cast(CodeGen::Address addr)
Definition Address.h:327
static bool ehCleanupScope()
static bool catchParamOp()
static bool incrementProfileCounter()
static bool setFunctionPersonality()
Represents a scope, including function bodies, compound statements, and the substatements of if/while...
The exceptions personality for a function.
bool usesFuncletPads() const
Does this personality use landingpads or the family of pad instructions designed to form funclets?
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