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
188static llvm::StringRef getPersonalityFn(CIRGenModule &cgm,
189 const EHPersonality &personality) {
190 // Create the personality function type: i32 (...)
191 mlir::Type i32Ty = cgm.getBuilder().getI32Type();
192 auto funcTy = cir::FuncType::get({}, i32Ty, /*isVarArg=*/true);
193
194 cir::FuncOp personalityFn = cgm.createRuntimeFunction(
195 funcTy, personality.personalityFn, mlir::ArrayAttr(), /*isLocal=*/true);
196
197 return personalityFn.getSymName();
198}
199
201 const llvm::Triple &triple = getTarget().getTriple();
202 if (cgm.getLangOpts().OpenMPIsTargetDevice &&
203 (triple.isNVPTX() || triple.isAMDGCN())) {
204 cgm.errorNYI("emitCXXThrowExpr OpenMP with NVPTX or AMDGCN Triples");
205 return;
206 }
207
208 if (const Expr *subExpr = e->getSubExpr()) {
209 QualType throwType = subExpr->getType();
210 if (throwType->isObjCObjectPointerType()) {
211 cgm.errorNYI("emitCXXThrowExpr ObjCObjectPointerType");
212 return;
213 }
214
215 cgm.getCXXABI().emitThrow(*this, e);
216 return;
217 }
218
219 cgm.getCXXABI().emitRethrow(*this, /*isNoReturn=*/true);
220}
221
223 // Make sure the exception object is cleaned up if there's an
224 // exception during initialization.
226
227 // __cxa_allocate_exception returns a void*; we need to cast this
228 // to the appropriate type for the object.
229 mlir::Type ty = convertTypeForMem(e->getType());
230 Address typedAddr = addr.withElementType(builder, ty);
231
232 // From LLVM's codegen:
233 // FIXME: this isn't quite right! If there's a final unelided call
234 // to a copy constructor, then according to [except.terminate]p1 we
235 // must call std::terminate() if that constructor throws, because
236 // technically that copy occurs after the exception expression is
237 // evaluated but before the exception is caught. But the best way
238 // to handle that is to teach EmitAggExpr to do the final copy
239 // differently if it can't be elided.
240 emitAnyExprToMem(e, typedAddr, e->getType().getQualifiers(),
241 /*isInitializer=*/true);
242
243 // Deactivate the cleanup block.
245}
246
247mlir::LogicalResult CIRGenFunction::emitCXXTryStmt(const CXXTryStmt &s) {
248 if (s.getTryBlock()->body_empty())
249 return mlir::LogicalResult::success();
250
251 mlir::Location loc = getLoc(s.getSourceRange());
252 // Create a scope to hold try local storage for catch params.
253
254 mlir::OpBuilder::InsertPoint scopeIP;
255 cir::ScopeOp::create(
256 builder, loc,
257 /*scopeBuilder=*/[&](mlir::OpBuilder &b, mlir::Location loc) {
258 scopeIP = builder.saveInsertionPoint();
259 });
260
261 mlir::OpBuilder::InsertionGuard guard(builder);
262 builder.restoreInsertionPoint(scopeIP);
263 mlir::LogicalResult result = emitCXXTryStmtUnderScope(s);
264 cir::YieldOp::create(builder, loc);
265 return result;
266}
267
268mlir::LogicalResult
270 const llvm::Triple &t = getTarget().getTriple();
271 // If we encounter a try statement on in an OpenMP target region offloaded to
272 // a GPU, we treat it as a basic block.
273 const bool isTargetDevice =
274 (cgm.getLangOpts().OpenMPIsTargetDevice && (t.isNVPTX() || t.isAMDGCN()));
275 if (isTargetDevice) {
276 cgm.errorNYI(
277 "emitCXXTryStmtUnderScope: OpenMP target region offloaded to GPU");
278 return mlir::success();
279 }
280
281 unsigned numHandlers = s.getNumHandlers();
282 mlir::Location tryLoc = getLoc(s.getBeginLoc());
283 mlir::OpBuilder::InsertPoint beginInsertTryBody;
284
285 bool hasCatchAll = false;
286 for (unsigned i = 0; i != numHandlers; ++i) {
287 hasCatchAll |= s.getHandler(i)->getExceptionDecl() == nullptr;
288 if (hasCatchAll)
289 break;
290 }
291
292 // Create the scope to represent only the C/C++ `try {}` part. However,
293 // don't populate right away. Create regions for the catch handlers,
294 // but don't emit the handler bodies yet. For now, only make sure the
295 // scope returns the exception information.
296 auto tryOp = cir::TryOp::create(
297 builder, tryLoc,
298 /*tryBuilder=*/
299 [&](mlir::OpBuilder &b, mlir::Location loc) {
300 beginInsertTryBody = builder.saveInsertionPoint();
301 },
302 /*handlersBuilder=*/
303 [&](mlir::OpBuilder &b, mlir::Location loc,
304 mlir::OperationState &result) {
305 mlir::OpBuilder::InsertionGuard guard(b);
306
307 // We create an extra region for an unwind catch handler in case the
308 // catch-all handler doesn't exists
309 unsigned numRegionsToCreate =
310 hasCatchAll ? numHandlers : numHandlers + 1;
311
312 for (unsigned i = 0; i != numRegionsToCreate; ++i) {
313 mlir::Region *region = result.addRegion();
314 builder.createBlock(region);
315 }
316 });
317
318 // Finally emit the body for try/catch.
319 {
320 mlir::Location loc = tryOp.getLoc();
321 mlir::OpBuilder::InsertionGuard guard(builder);
322 builder.restoreInsertionPoint(beginInsertTryBody);
323 CIRGenFunction::LexicalScope tryScope{*this, loc,
324 builder.getInsertionBlock()};
325
326 tryScope.setAsTry(tryOp);
327
328 // Attach the basic blocks for the catch regions.
329 enterCXXTryStmt(s, tryOp);
330
331 // Emit the body for the `try {}` part.
332 {
333 mlir::OpBuilder::InsertionGuard guard(builder);
334 CIRGenFunction::LexicalScope tryBodyScope{*this, loc,
335 builder.getInsertionBlock()};
336 if (emitStmt(s.getTryBlock(), /*useCurrentScope=*/true).failed())
337 return mlir::failure();
338 }
339
340 // Emit catch clauses.
342 }
343
344 return mlir::success();
345}
346
347void CIRGenFunction::enterCXXTryStmt(const CXXTryStmt &s, cir::TryOp tryOp,
348 bool isFnTryBlock) {
349 unsigned numHandlers = s.getNumHandlers();
350 EHCatchScope *catchScope = ehStack.pushCatch(numHandlers);
351 for (unsigned i = 0; i != numHandlers; ++i) {
352 const CXXCatchStmt *catchStmt = s.getHandler(i);
353 if (catchStmt->getExceptionDecl()) {
354 cgm.errorNYI("enterCXXTryStmt: CatchStmt with ExceptionDecl");
355 return;
356 }
357
358 // No exception decl indicates '...', a catch-all.
359 mlir::Region *handler = &tryOp.getHandlerRegions()[i];
360 catchScope->setHandler(i, cgm.getCXXABI().getCatchAllTypeInfo(), handler,
361 s.getHandler(i));
362
363 // Under async exceptions, catch(...) needs to catch HW exception too
364 // Mark scope with SehTryBegin as a SEH __try scope
365 if (getLangOpts().EHAsynch) {
366 cgm.errorNYI("enterCXXTryStmt: EHAsynch");
367 return;
368 }
369 }
370}
371
372void CIRGenFunction::exitCXXTryStmt(const CXXTryStmt &s, bool isFnTryBlock) {
373 unsigned numHandlers = s.getNumHandlers();
374 EHCatchScope &catchScope = cast<EHCatchScope>(*ehStack.begin());
375 assert(catchScope.getNumHandlers() == numHandlers);
376 cir::TryOp tryOp = curLexScope->getTry();
377
378 // If the catch was not required, bail out now.
379 if (!catchScope.mayThrow()) {
380 catchScope.clearHandlerBlocks();
381 ehStack.popCatch();
382
383 // Drop all basic block from all catch regions.
384 SmallVector<mlir::Block *> eraseBlocks;
385 for (mlir::Region &handlerRegion : tryOp.getHandlerRegions()) {
386 if (handlerRegion.empty())
387 continue;
388
389 for (mlir::Block &b : handlerRegion.getBlocks())
390 eraseBlocks.push_back(&b);
391 }
392
393 for (mlir::Block *b : eraseBlocks)
394 b->erase();
395
396 tryOp.setHandlerTypesAttr({});
397 return;
398 }
399
400 // Copy the handler blocks off before we pop the EH stack. Emitting
401 // the handlers might scribble on this memory.
402 SmallVector<EHCatchScope::Handler> handlers(catchScope.begin(),
403 catchScope.begin() + numHandlers);
404
405 ehStack.popCatch();
406
407 // Determine if we need an implicit rethrow for all these catch handlers;
408 // see the comment below.
409 bool doImplicitRethrow =
411
412 // Wasm uses Windows-style EH instructions, but merges all catch clauses into
413 // one big catchpad. So we save the old funclet pad here before we traverse
414 // each catch handler.
415 if (EHPersonality::get(*this).isWasmPersonality()) {
416 cgm.errorNYI("exitCXXTryStmt: WASM personality");
417 return;
418 }
419
420 bool hasCatchAll = false;
421 for (auto &handler : llvm::reverse(handlers)) {
422 hasCatchAll |= handler.isCatchAll();
423 mlir::Region *catchRegion = handler.region;
424 const CXXCatchStmt *catchStmt = handler.stmt;
425
426 mlir::OpBuilder::InsertionGuard guard(builder);
427 builder.setInsertionPointToStart(&catchRegion->front());
428
429 // Enter a cleanup scope, including the catch variable and the
430 // end-catch.
431 RunCleanupsScope catchScope(*this);
432
433 // Initialize the catch variable and set up the cleanups.
435 cgm.getCXXABI().emitBeginCatch(*this, catchStmt);
436
437 // Emit the PGO counter increment.
439
440 // Perform the body of the catch.
441 [[maybe_unused]] mlir::LogicalResult emitResult =
442 emitStmt(catchStmt->getHandlerBlock(), /*useCurrentScope=*/true);
443 assert(emitResult.succeeded() && "failed to emit catch handler block");
444
446 cir::YieldOp::create(builder, tryOp->getLoc());
447
448 // [except.handle]p11:
449 // The currently handled exception is rethrown if control
450 // reaches the end of a handler of the function-try-block of a
451 // constructor or destructor.
452
453 // It is important that we only do this on fallthrough and not on
454 // return. Note that it's illegal to put a return in a
455 // constructor function-try-block's catch handler (p14), so this
456 // really only applies to destructors.
457 if (doImplicitRethrow) {
458 cgm.errorNYI("exitCXXTryStmt: doImplicitRethrow");
459 return;
460 }
461
462 // Fall out through the catch cleanups.
463 catchScope.forceCleanup();
464 }
465
466 // Because in wasm we merge all catch clauses into one big catchpad, in case
467 // none of the types in catch handlers matches after we test against each of
468 // them, we should unwind to the next EH enclosing scope. We generate a call
469 // to rethrow function here to do that.
470 if (EHPersonality::get(*this).isWasmPersonality() && !hasCatchAll) {
471 cgm.errorNYI("exitCXXTryStmt: WASM personality without catch all");
472 }
473
475}
476
478 assert(ehStack.requiresCatchOrCleanup());
479 assert(!cgm.getLangOpts().IgnoreExceptions &&
480 "LandingPad should not be emitted when -fignore-exceptions are in "
481 "effect.");
482
483 EHScope &innermostEHScope = *ehStack.find(ehStack.getInnermostEHScope());
484 switch (innermostEHScope.getKind()) {
486 cgm.errorNYI("populateCatchHandlers: terminate");
487 return;
488
489 case EHScope::Catch:
490 case EHScope::Cleanup:
491 case EHScope::Filter:
492 // CIR does not cache landing pads.
493 break;
494 }
495
496 // If there's an existing TryOp, it means we got a `cir.try` scope
497 // that leads to this "landing pad" creation site. Otherwise, exceptions
498 // are enabled but a throwing function is called anyways (common pattern
499 // with function local static initializers).
500 mlir::ArrayAttr handlerTypesAttr = tryOp.getHandlerTypesAttr();
501 if (!handlerTypesAttr || handlerTypesAttr.empty()) {
502 // Accumulate all the handlers in scope.
503 bool hasCatchAll = false;
505 for (EHScopeStack::iterator i = ehStack.begin(), e = ehStack.end(); i != e;
506 ++i) {
507 switch (i->getKind()) {
508 case EHScope::Cleanup:
509 cgm.errorNYI("emitLandingPad: Cleanup");
510 return;
511
512 case EHScope::Filter:
513 cgm.errorNYI("emitLandingPad: Filter");
514 return;
515
517 cgm.errorNYI("emitLandingPad: Terminate");
518 return;
519
520 case EHScope::Catch:
521 break;
522 } // end switch
523
524 EHCatchScope &catchScope = cast<EHCatchScope>(*i);
525 for (const EHCatchScope::Handler &handler :
526 llvm::make_range(catchScope.begin(), catchScope.end())) {
527 assert(handler.type.flags == 0 &&
528 "landingpads do not support catch handler flags");
529
530 // If this is a catch-all, register that and abort.
531 if (handler.isCatchAll()) {
532 assert(!hasCatchAll);
533 hasCatchAll = true;
534 break;
535 }
536
537 cgm.errorNYI("emitLandingPad: non catch-all");
538 return;
539 }
540
541 if (hasCatchAll)
542 break;
543 }
544
545 if (hasCatchAll) {
546 handlerAttrs.push_back(cir::CatchAllAttr::get(&getMLIRContext()));
547 } else {
548 cgm.errorNYI("emitLandingPad: non catch-all");
549 return;
550 }
551
552 // Add final array of clauses into TryOp.
553 tryOp.setHandlerTypesAttr(
554 mlir::ArrayAttr::get(&getMLIRContext(), handlerAttrs));
555 }
556
557 // In traditional LLVM codegen. this tells the backend how to generate the
558 // landing pad by generating a branch to the dispatch block. In CIR,
559 // this is used to populate blocks for later filing during
560 // cleanup handling.
561 populateEHCatchRegions(ehStack.getInnermostEHScope(), tryOp);
562}
563
564// Differently from LLVM traditional codegen, there are no dispatch blocks
565// to look at given cir.try_call does not jump to blocks like invoke does.
566// However.
568 cir::TryOp tryOp) {
569 if (EHPersonality::get(*this).usesFuncletPads()) {
570 cgm.errorNYI("getEHDispatchBlock: usesFuncletPads");
571 return;
572 }
573
574 // Otherwise, we should look at the actual scope.
575 EHScope &ehScope = *ehStack.find(scope);
576 bool mayThrow = ehScope.mayThrow();
577
578 mlir::Block *originalBlock = nullptr;
579 if (mayThrow && tryOp) {
580 // If the dispatch is cached but comes from a different tryOp, make sure:
581 // - Populate current `tryOp` with a new dispatch block regardless.
582 // - Update the map to enqueue new dispatchBlock to also get a cleanup. See
583 // code at the end of the function.
584 cgm.errorNYI("getEHDispatchBlock: mayThrow & tryOp");
585 return;
586 }
587
588 if (!mayThrow) {
589 switch (ehScope.getKind()) {
590 case EHScope::Catch: {
591 // LLVM does some optimization with branches here, CIR just keep track of
592 // the corresponding calls.
593 EHCatchScope &catchScope = cast<EHCatchScope>(ehScope);
594 if (catchScope.getNumHandlers() == 1 &&
595 catchScope.getHandler(0).isCatchAll()) {
596 mayThrow = true;
597 break;
598 }
599 cgm.errorNYI("getEHDispatchBlock: mayThrow non-catch all");
600 return;
601 }
602 case EHScope::Cleanup: {
603 cgm.errorNYI("getEHDispatchBlock: mayThrow & cleanup");
604 return;
605 }
606 case EHScope::Filter: {
607 cgm.errorNYI("getEHDispatchBlock: mayThrow & Filter");
608 return;
609 }
610 case EHScope::Terminate: {
611 cgm.errorNYI("getEHDispatchBlock: mayThrow & Terminate");
612 return;
613 }
614 }
615 }
616
617 if (originalBlock) {
618 cgm.errorNYI("getEHDispatchBlock: originalBlock");
619 return;
620 }
621
622 ehScope.setMayThrow(mayThrow);
623}
624
625// in classic codegen this function is mapping to `isInvokeDest` previously and
626// currently it's mapping to the conditions that performs early returns in
627// `getInvokeDestImpl`, in CIR we need the condition to know if the EH scope may
628// throw exception or now.
630 // If exceptions are disabled/ignored and SEH is not in use, then there is no
631 // invoke destination. SEH "works" even if exceptions are off. In practice,
632 // this means that C++ destructors and other EH cleanups don't run, which is
633 // consistent with MSVC's behavior, except in the presence of -EHa
634 const LangOptions &lo = cgm.getLangOpts();
635 if (!lo.Exceptions || lo.IgnoreExceptions) {
636 if (!lo.Borland && !lo.MicrosoftExt)
637 return false;
638 cgm.errorNYI("isInvokeDest: no exceptions or ignore exception");
639 return false;
640 }
641
642 // CUDA device code doesn't have exceptions.
643 if (lo.CUDA && lo.CUDAIsDevice)
644 return false;
645
646 return ehStack.requiresCatchOrCleanup();
647}
648
649// In classic codegen this function is equivalent to `getInvokeDestImpl`, in
650// ClangIR we don't need to return to return any landing pad, we just need to
651// populate the catch handlers if they are required
653 assert(ehStack.requiresCatchOrCleanup());
654 assert(!ehStack.empty());
655
656 const EHPersonality &personality = EHPersonality::get(*this);
657
658 // Set personality function if not already set
659 auto funcOp = mlir::cast<cir::FuncOp>(curFn);
660 if (!funcOp.getPersonality())
661 funcOp.setPersonality(getPersonalityFn(cgm, personality));
662
663 // CIR does not cache landing pads.
664 if (personality.usesFuncletPads()) {
665 cgm.errorNYI("getInvokeDestImpl: usesFuncletPads");
666 } else {
668 }
669}
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()
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)
mlir::Operation * curFn
The current function or global initializer that is generated code for.
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.
cir::FuncOp createRuntimeFunction(cir::FuncType ty, llvm::StringRef name, mlir::ArrayAttr={}, bool isLocal=false, bool assumeConvergent=false)
CIRGenBuilderTy & getBuilder()
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 currentFuncletPad()
static bool incrementProfileCounter()
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