17#include "llvm/Support/SaveAndRestore.h"
32 "__gxx_personality_sj0",
nullptr};
34 "__gxx_personality_seh0",
nullptr};
36 "objc_exception_throw"};
38 "__gnu_objc_personality_sj0",
"objc_exception_throw"};
40 "__gnu_objc_personality_seh0",
"objc_exception_throw"};
42 "__gnustep_objcxx_personality_v0",
nullptr};
44 "__gnustep_objc_personality_v0",
nullptr};
48 "__C_specific_handler",
nullptr};
50 "__CxxFrameHandler3",
nullptr};
52 "__gxx_wasm_personality_v0",
nullptr};
60 const llvm::Triple &triple = target.
getTriple();
61 if (triple.isWindowsMSVCEnvironment())
75 const llvm::Triple &triple = target.
getTriple();
76 if (triple.isWindowsMSVCEnvironment())
98 llvm_unreachable(
"bad runtime kind");
103 const llvm::Triple &triple = target.
getTriple();
104 if (triple.isWindowsMSVCEnvironment())
106 if (triple.isOSAIX())
124 if (target.
getTriple().isWindowsMSVCEnvironment())
150 llvm_unreachable(
"bad runtime kind");
154 return triple.getArch() == llvm::Triple::x86
184 return get(cgf.
cgm, dyn_cast_or_null<FunctionDecl>(fg));
190 mlir::Type i32Ty = cgm.
getBuilder().getI32Type();
191 auto funcTy = cir::FuncType::get({}, i32Ty,
true);
196 return personalityFn.getSymName();
201 if (
cgm.getLangOpts().OpenMPIsTargetDevice &&
202 (triple.isNVPTX() || triple.isAMDGCN())) {
203 cgm.errorNYI(
"emitCXXThrowExpr OpenMP with NVPTX or AMDGCN Triples");
208 QualType throwType = subExpr->getType();
210 cgm.errorNYI(
"emitCXXThrowExpr ObjCObjectPointerType");
214 cgm.getCXXABI().emitThrow(*
this, e);
218 cgm.getCXXABI().emitRethrow(*
this,
true);
252 if (rethrowName !=
nullptr && !isCleanup) {
253 cgm.errorNYI(
"populateUnwindResumeBlock CatchallRethrowFn");
257 unsigned regionsNum = tryOp->getNumRegions();
258 mlir::Region *unwindRegion = &tryOp->getRegion(regionsNum - 1);
259 mlir::Block *unwindResumeBlock = &unwindRegion->front();
260 if (!unwindResumeBlock->empty())
264 mlir::OpBuilder::InsertionGuard guard(builder);
265 builder.setInsertionPointToStart(unwindResumeBlock);
266 cir::ResumeOp::create(builder, tryOp.getLoc());
270 if (
s.getTryBlock()->body_empty())
271 return mlir::LogicalResult::success();
273 mlir::Location loc =
getLoc(
s.getSourceRange());
276 mlir::OpBuilder::InsertPoint scopeIP;
277 cir::ScopeOp::create(
279 [&](mlir::OpBuilder &
b, mlir::Location loc) {
280 scopeIP = builder.saveInsertionPoint();
283 mlir::OpBuilder::InsertionGuard guard(builder);
284 builder.restoreInsertionPoint(scopeIP);
286 cir::YieldOp::create(builder, loc);
295 const bool isTargetDevice =
296 (
cgm.getLangOpts().OpenMPIsTargetDevice && (t.isNVPTX() || t.isAMDGCN()));
297 if (isTargetDevice) {
299 "emitCXXTryStmtUnderScope: OpenMP target region offloaded to GPU");
300 return mlir::success();
303 unsigned numHandlers =
s.getNumHandlers();
304 mlir::Location tryLoc =
getLoc(
s.getBeginLoc());
305 mlir::OpBuilder::InsertPoint beginInsertTryBody;
307 bool hasCatchAll =
false;
308 for (
unsigned i = 0; i != numHandlers; ++i) {
309 hasCatchAll |=
s.getHandler(i)->getExceptionDecl() ==
nullptr;
318 auto tryOp = cir::TryOp::create(
321 [&](mlir::OpBuilder &
b, mlir::Location loc) {
322 beginInsertTryBody = builder.saveInsertionPoint();
325 [&](mlir::OpBuilder &
b, mlir::Location loc,
326 mlir::OperationState &result) {
327 mlir::OpBuilder::InsertionGuard guard(
b);
331 unsigned numRegionsToCreate =
332 hasCatchAll ? numHandlers : numHandlers + 1;
334 for (
unsigned i = 0; i != numRegionsToCreate; ++i) {
335 mlir::Region *region = result.addRegion();
336 builder.createBlock(region);
342 mlir::Location loc = tryOp.getLoc();
343 mlir::OpBuilder::InsertionGuard guard(builder);
344 builder.restoreInsertionPoint(beginInsertTryBody);
346 builder.getInsertionBlock()};
355 mlir::OpBuilder::InsertionGuard guard(builder);
357 builder.getInsertionBlock()};
358 if (
emitStmt(
s.getTryBlock(),
true).failed())
359 return mlir::failure();
366 return mlir::success();
374 cgf.
cgm.
errorNYI(
"emitCatchDispatchBlock: WasmPersonality");
379 cgf.
cgm.
errorNYI(
"emitCatchDispatchBlock: usesFuncletPads");
383 assert(std::find_if(catchScope.
begin(), catchScope.
end(),
384 [](
const auto &handler) {
385 return !handler.type.rtti && handler.type.flags != 0;
386 }) == catchScope.
end() &&
387 "catch handler without type value or with not supported flags");
391 if (!std::prev(catchScope.
end())->isCatchAll())
397 unsigned numHandlers =
s.getNumHandlers();
399 for (
unsigned i = 0; i != numHandlers; ++i) {
401 mlir::Region *handler = &tryOp.getHandlerRegions()[i];
410 QualType caughtType =
cgm.getASTContext().getUnqualifiedArrayType(
413 cgm.errorNYI(
"enterCXXTryStmt: caughtType ObjCObjectPointerType");
420 catchScope->
setHandler(i, typeInfo, handler, catchStmt);
423 catchScope->
setHandler(i,
cgm.getCXXABI().getCatchAllTypeInfo(), handler,
430 cgm.errorNYI(
"enterCXXTryStmt: EHAsynch");
437 unsigned numHandlers =
s.getNumHandlers();
449 for (mlir::Region &handlerRegion : tryOp.getHandlerRegions()) {
450 if (handlerRegion.empty())
453 for (mlir::Block &
b : handlerRegion.getBlocks())
454 eraseBlocks.push_back(&
b);
457 for (mlir::Block *
b : eraseBlocks)
460 tryOp.setHandlerTypesAttr({});
470 catchScope.
begin() + numHandlers);
476 bool doImplicitRethrow =
483 cgm.errorNYI(
"exitCXXTryStmt: WASM personality");
487 bool hasCatchAll =
false;
488 for (
auto &handler : llvm::reverse(handlers)) {
489 hasCatchAll |= handler.isCatchAll();
490 mlir::Region *catchRegion = handler.region;
493 mlir::OpBuilder::InsertionGuard guard(builder);
494 builder.setInsertionPointToStart(&catchRegion->front());
502 cgm.getCXXABI().emitBeginCatch(*
this, catchStmt);
508 [[maybe_unused]] mlir::LogicalResult emitResult =
510 assert(emitResult.succeeded() &&
"failed to emit catch handler block");
521 if (doImplicitRethrow) {
522 cgm.errorNYI(
"exitCXXTryStmt: doImplicitRethrow");
535 cgm.errorNYI(
"exitCXXTryStmt: WASM personality without catch all");
542 assert(
ehStack.requiresCatchOrCleanup());
543 assert(!
cgm.getLangOpts().IgnoreExceptions &&
544 "LandingPad should not be emitted when -fignore-exceptions are in "
548 switch (innermostEHScope.
getKind()) {
550 cgm.errorNYI(
"populateCatchHandlers: terminate");
564 mlir::ArrayAttr handlerTypesAttr = tryOp.getHandlerTypesAttr();
565 if (!handlerTypesAttr || handlerTypesAttr.empty()) {
567 bool hasCatchAll =
false;
572 switch (i->getKind()) {
574 cgm.errorNYI(
"emitLandingPad: Cleanup");
578 cgm.errorNYI(
"emitLandingPad: Filter");
582 cgm.errorNYI(
"emitLandingPad: Terminate");
591 llvm::make_range(catchScope.
begin(), catchScope.
end())) {
592 assert(handler.type.flags == 0 &&
593 "landingpads do not support catch handler flags");
596 if (handler.isCatchAll()) {
597 assert(!hasCatchAll);
604 if (catchTypes.insert(handler.type.rtti).second)
605 handlerAttrs.push_back(handler.type.rtti);
613 handlerAttrs.push_back(cir::CatchAllAttr::get(&
getMLIRContext()));
623 tryOp.setHandlerTypesAttr(
640 cgm.errorNYI(
"getEHDispatchBlock: usesFuncletPads");
646 if (scope ==
ehStack.stable_end()) {
655 mlir::Block *originalBlock =
nullptr;
656 if (mayThrow && tryOp) {
661 cgm.errorNYI(
"getEHDispatchBlock: mayThrow & tryOp");
683 cgm.errorNYI(
"getEHDispatchBlock: mayThrow & cleanup");
687 cgm.errorNYI(
"getEHDispatchBlock: mayThrow & Filter");
691 cgm.errorNYI(
"getEHDispatchBlock: mayThrow & Terminate");
698 cgm.errorNYI(
"getEHDispatchBlock: originalBlock");
715 if (!lo.Exceptions || lo.IgnoreExceptions) {
716 if (!lo.Borland && !lo.MicrosoftExt)
718 cgm.errorNYI(
"isInvokeDest: no exceptions or ignore exception");
723 if (lo.CUDA && lo.CUDAIsDevice)
726 return ehStack.requiresCatchOrCleanup();
733 assert(
ehStack.requiresCatchOrCleanup());
739 auto funcOp = mlir::cast<cir::FuncOp>(
curFn);
740 if (!funcOp.getPersonality())
745 cgm.errorNYI(
"getInvokeDestImpl: usesFuncletPads");
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)
static void emitCatchDispatchBlock(CIRGenFunction &cgf, EHCatchScope &catchScope, cir::TryOp tryOp)
Emit the structure of the dispatch block for the given catch scope.
__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)
void populateUnwindResumeBlock(bool isCleanup, cir::TryOp tryOp)
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)
bool isCatchOrCleanupRequired()
LexicalScope * curLexScope
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.
DiagnosticBuilder errorNYI(SourceLocation, llvm::StringRef)
Helpers to emit "not yet implemented" error diagnostics.
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)
void clearHandlerBlocks()
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)
EHScopeStack::stable_iterator getEnclosingEHScope() const
CXXCatchStmt - This represents a C++ catch block.
Stmt * getHandlerBlock() const
VarDecl * getExceptionDecl() const
QualType getCaughtType() const
A C++ throw-expression (C++ [except.throw]).
const Expr * getSubExpr() const
CXXTryStmt - A C++ try block, including all handlers.
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.
Represents a function declaration or definition.
bool usesSEHTry() const
Indicates the function uses __try.
const Decl * getDecl() const
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
clang::ObjCRuntime ObjCRuntime
const VersionTuple & getVersion() const
@ MacOSX
'macosx' is the Apple-provided NeXT-derived runtime on Mac OS X platforms that use the non-fragile AB...
@ FragileMacOSX
'macosx-fragile' is the Apple-provided NeXT-derived runtime on Mac OS X platforms that use the fragil...
@ GNUstep
'gnustep' is the modern non-fragile GNUstep runtime.
@ ObjFW
'objfw' is the Objective-C runtime included in ObjFW
@ iOS
'ios' is the Apple-provided NeXT-derived runtime on iOS or the iOS simulator; it is always non-fragil...
@ GCC
'gcc' is the Objective-C runtime shipped with GCC, implementing a fragile Objective-C ABI
@ WatchOS
'watchos' is a variant of iOS for Apple's watchOS.
A (possibly-)qualified type.
Qualifiers getQualifiers() const
Retrieve the set of qualifiers applied to this type.
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
The collection of all-type qualifiers we support.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Exposes information about the current target.
const llvm::Triple & getTriple() const
Returns the target triple of the primary target.
bool isObjCObjectPointerType() const
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
U cast(CodeGen::Address addr)
static bool ehScopeFilter()
static bool ehCleanupScope()
static bool currentFuncletPad()
static bool incrementProfileCounter()
Represents a scope, including function bodies, compound statements, and the substatements of if/while...
void setAsTry(cir::TryOp op)
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.
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
const char * personalityFn
const char * catchallRethrowFn
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