18#include "llvm/Support/SaveAndRestore.h"
33 "__gxx_personality_sj0",
nullptr};
35 "__gxx_personality_seh0",
nullptr};
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};
49 "__C_specific_handler",
nullptr};
51 "__CxxFrameHandler3",
nullptr};
53 "__gxx_wasm_personality_v0",
nullptr};
61 const llvm::Triple &triple = target.
getTriple();
62 if (triple.isWindowsMSVCEnvironment())
76 const llvm::Triple &triple = target.
getTriple();
77 if (triple.isWindowsMSVCEnvironment())
99 llvm_unreachable(
"bad runtime kind");
104 const llvm::Triple &triple = target.
getTriple();
105 if (triple.isWindowsMSVCEnvironment())
107 if (triple.isOSAIX())
125 if (target.
getTriple().isWindowsMSVCEnvironment())
151 llvm_unreachable(
"bad runtime kind");
155 return triple.getArch() == llvm::Triple::x86
185 return get(cgf.
cgm, dyn_cast_or_null<FunctionDecl>(fg));
191 mlir::Type i32Ty = cgm.
getBuilder().getI32Type();
192 auto funcTy = cir::FuncType::get({}, i32Ty,
true);
197 return personalityFn.getSymName();
202 if (
cgm.getLangOpts().OpenMPIsTargetDevice &&
203 (triple.isNVPTX() || triple.isAMDGCN())) {
204 cgm.errorNYI(
"emitCXXThrowExpr OpenMP with NVPTX or AMDGCN Triples");
209 QualType throwType = subExpr->getType();
211 cgm.errorNYI(
"emitCXXThrowExpr ObjCObjectPointerType");
215 cgm.getCXXABI().emitThrow(*
this, e);
219 cgm.getCXXABI().emitRethrow(*
this,
true);
253 if (rethrowName !=
nullptr && !isCleanup) {
254 cgm.errorNYI(
"populateUnwindResumeBlock CatchallRethrowFn");
258 unsigned regionsNum = tryOp->getNumRegions();
259 mlir::Region *unwindRegion = &tryOp->getRegion(regionsNum - 1);
260 mlir::Block *unwindResumeBlock = &unwindRegion->front();
261 if (!unwindResumeBlock->empty())
265 mlir::OpBuilder::InsertionGuard guard(builder);
266 builder.setInsertionPointToStart(unwindResumeBlock);
267 cir::ResumeOp::create(builder, tryOp.getLoc());
271 if (
s.getTryBlock()->body_empty())
272 return mlir::LogicalResult::success();
274 mlir::Location loc =
getLoc(
s.getSourceRange());
277 mlir::OpBuilder::InsertPoint scopeIP;
278 cir::ScopeOp::create(
280 [&](mlir::OpBuilder &
b, mlir::Location loc) {
281 scopeIP = builder.saveInsertionPoint();
284 mlir::OpBuilder::InsertionGuard guard(builder);
285 builder.restoreInsertionPoint(scopeIP);
287 cir::YieldOp::create(builder, loc);
296 const bool isTargetDevice =
297 (
cgm.getLangOpts().OpenMPIsTargetDevice && (t.isNVPTX() || t.isAMDGCN()));
298 if (isTargetDevice) {
300 "emitCXXTryStmtUnderScope: OpenMP target region offloaded to GPU");
301 return mlir::success();
304 unsigned numHandlers =
s.getNumHandlers();
305 mlir::Location tryLoc =
getLoc(
s.getBeginLoc());
306 mlir::OpBuilder::InsertPoint beginInsertTryBody;
308 bool hasCatchAll =
false;
309 for (
unsigned i = 0; i != numHandlers; ++i) {
310 hasCatchAll |=
s.getHandler(i)->getExceptionDecl() ==
nullptr;
319 auto tryOp = cir::TryOp::create(
322 [&](mlir::OpBuilder &
b, mlir::Location loc) {
323 beginInsertTryBody = builder.saveInsertionPoint();
326 [&](mlir::OpBuilder &
b, mlir::Location loc,
327 mlir::OperationState &result) {
328 mlir::OpBuilder::InsertionGuard guard(
b);
332 unsigned numRegionsToCreate =
333 hasCatchAll ? numHandlers : numHandlers + 1;
335 for (
unsigned i = 0; i != numRegionsToCreate; ++i) {
336 mlir::Region *region = result.addRegion();
337 builder.createBlock(region);
343 mlir::Location loc = tryOp.getLoc();
344 mlir::OpBuilder::InsertionGuard guard(builder);
345 builder.restoreInsertionPoint(beginInsertTryBody);
347 builder.getInsertionBlock()};
356 mlir::OpBuilder::InsertionGuard guard(builder);
358 builder.getInsertionBlock()};
359 if (
emitStmt(
s.getTryBlock(),
true).failed())
360 return mlir::failure();
367 return mlir::success();
375 cgf.
cgm.
errorNYI(
"emitCatchDispatchBlock: WasmPersonality");
380 cgf.
cgm.
errorNYI(
"emitCatchDispatchBlock: usesFuncletPads");
384 assert(std::find_if(catchScope.
begin(), catchScope.
end(),
385 [](
const auto &handler) {
386 return !handler.type.rtti && handler.type.flags != 0;
387 }) == catchScope.
end() &&
388 "catch handler without type value or with not supported flags");
392 if (!std::prev(catchScope.
end())->isCatchAll())
398 unsigned numHandlers =
s.getNumHandlers();
400 for (
unsigned i = 0; i != numHandlers; ++i) {
402 mlir::Region *handler = &tryOp.getHandlerRegions()[i];
411 QualType caughtType =
cgm.getASTContext().getUnqualifiedArrayType(
414 cgm.errorNYI(
"enterCXXTryStmt: caughtType ObjCObjectPointerType");
421 catchScope->
setHandler(i, typeInfo, handler, catchStmt);
424 catchScope->
setHandler(i,
cgm.getCXXABI().getCatchAllTypeInfo(), handler,
431 cgm.errorNYI(
"enterCXXTryStmt: EHAsynch");
438 unsigned numHandlers =
s.getNumHandlers();
450 for (mlir::Region &handlerRegion : tryOp.getHandlerRegions()) {
451 if (handlerRegion.empty())
454 for (mlir::Block &
b : handlerRegion.getBlocks())
455 eraseBlocks.push_back(&
b);
458 for (mlir::Block *
b : eraseBlocks)
461 tryOp.setHandlerTypesAttr({});
471 catchScope.
begin() + numHandlers);
477 bool doImplicitRethrow =
484 cgm.errorNYI(
"exitCXXTryStmt: WASM personality");
488 bool hasCatchAll =
false;
489 for (
auto &handler : llvm::reverse(handlers)) {
490 hasCatchAll |= handler.isCatchAll();
491 mlir::Region *catchRegion = handler.region;
494 mlir::OpBuilder::InsertionGuard guard(builder);
495 builder.setInsertionPointToStart(&catchRegion->front());
503 cgm.getCXXABI().emitBeginCatch(*
this, catchStmt);
509 [[maybe_unused]] mlir::LogicalResult emitResult =
511 assert(emitResult.succeeded() &&
"failed to emit catch handler block");
522 if (doImplicitRethrow) {
523 cgm.errorNYI(
"exitCXXTryStmt: doImplicitRethrow");
536 cgm.errorNYI(
"exitCXXTryStmt: WASM personality without catch all");
543 assert(
ehStack.requiresCatchOrCleanup());
544 assert(!
cgm.getLangOpts().IgnoreExceptions &&
545 "LandingPad should not be emitted when -fignore-exceptions are in "
549 switch (innermostEHScope.
getKind()) {
551 cgm.errorNYI(
"populateCatchHandlers: terminate");
565 mlir::ArrayAttr handlerTypesAttr = tryOp.getHandlerTypesAttr();
566 if (!handlerTypesAttr || handlerTypesAttr.empty()) {
568 bool hasCatchAll =
false;
573 switch (i->getKind()) {
575 cgm.errorNYI(
"emitLandingPad: Cleanup");
579 cgm.errorNYI(
"emitLandingPad: Filter");
583 cgm.errorNYI(
"emitLandingPad: Terminate");
592 llvm::make_range(catchScope.
begin(), catchScope.
end())) {
593 assert(handler.type.flags == 0 &&
594 "landingpads do not support catch handler flags");
597 if (handler.isCatchAll()) {
598 assert(!hasCatchAll);
605 if (catchTypes.insert(handler.type.rtti).second)
606 handlerAttrs.push_back(handler.type.rtti);
614 handlerAttrs.push_back(cir::CatchAllAttr::get(&
getMLIRContext()));
624 tryOp.setHandlerTypesAttr(
641 cgm.errorNYI(
"getEHDispatchBlock: usesFuncletPads");
647 if (scope ==
ehStack.stable_end()) {
656 mlir::Block *originalBlock =
nullptr;
657 if (mayThrow && tryOp) {
662 cgm.errorNYI(
"getEHDispatchBlock: mayThrow & tryOp");
684 cgm.errorNYI(
"getEHDispatchBlock: mayThrow & cleanup");
688 cgm.errorNYI(
"getEHDispatchBlock: mayThrow & Filter");
692 cgm.errorNYI(
"getEHDispatchBlock: mayThrow & Terminate");
699 cgm.errorNYI(
"getEHDispatchBlock: originalBlock");
716 if (!lo.Exceptions || lo.IgnoreExceptions) {
717 if (!lo.Borland && !lo.MicrosoftExt)
719 cgm.errorNYI(
"isInvokeDest: no exceptions or ignore exception");
724 if (lo.CUDA && lo.CUDAIsDevice)
727 return ehStack.requiresCatchOrCleanup();
734 assert(
ehStack.requiresCatchOrCleanup());
740 auto funcOp = mlir::cast<cir::FuncOp>(
curFn);
741 if (!funcOp.getPersonality())
746 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