15#include "mlir/IR/Block.h"
16#include "mlir/IR/Location.h"
20#include "llvm/Support/SaveAndRestore.h"
35 "__gxx_personality_sj0",
nullptr};
37 "__gxx_personality_seh0",
nullptr};
39 "objc_exception_throw"};
41 "__gnu_objc_personality_sj0",
"objc_exception_throw"};
43 "__gnu_objc_personality_seh0",
"objc_exception_throw"};
45 "__gnustep_objcxx_personality_v0",
nullptr};
47 "__gnustep_objc_personality_v0",
nullptr};
51 "__C_specific_handler",
nullptr};
53 "__CxxFrameHandler3",
nullptr};
55 "__gxx_wasm_personality_v0",
nullptr};
63 const llvm::Triple &triple = target.
getTriple();
64 if (triple.isWindowsMSVCEnvironment())
78 const llvm::Triple &triple = target.
getTriple();
79 if (triple.isWindowsMSVCEnvironment())
101 llvm_unreachable(
"bad runtime kind");
106 const llvm::Triple &triple = target.
getTriple();
107 if (triple.isWindowsMSVCEnvironment())
109 if (triple.isOSAIX())
127 if (target.
getTriple().isWindowsMSVCEnvironment())
153 llvm_unreachable(
"bad runtime kind");
157 return triple.getArch() == llvm::Triple::x86
187 return get(cgf.
cgm, dyn_cast_or_null<FunctionDecl>(fg));
194 auto funcTy = cir::FuncType::get({}, i32Ty,
true);
199 return personalityFn.getSymName();
203 if (!
cgm.getLangOpts().CXXExceptions)
206 const FunctionDecl *fd = dyn_cast_or_null<FunctionDecl>(d);
210 if (
const CapturedDecl *cd = dyn_cast_or_null<CapturedDecl>(d)) {
212 cgm.errorNYI(cd->getSourceRange(),
213 "emitStartEHSpec CapturedDecl nothrow");
228 !
cgm.getCodeGenOpts().hasWasmExceptions());
239 if (
getTarget().getCXXABI().isMicrosoft())
246 if (
cgm.getCodeGenOpts().hasWasmExceptions()) {
248 diag::warn_wasm_dynamic_exception_spec_ignored)
258 if (
getTarget().getCXXABI() == TargetCXXABI::WebAssembly &&
259 (
cgm.getCodeGenOpts().getExceptionHandling() ==
261 cgm.getCodeGenOpts().getExceptionHandling() ==
265 diag::warn_wasm_dynamic_exception_spec_ignored)
267 }
else if (!needsTerminate) {
277 permittedTypes.push_back(
278 cgm.getAddrOfRTTIDescriptor(loc, exceptType,
true));
282 cir::FuncOp funcOp = mlir::cast<cir::FuncOp>(
curFn);
283 if (!funcOp.getPersonality())
286 bool emptyFilter = permittedTypes.empty();
291 [](mlir::OpBuilder &, mlir::Location) {},
293 [&](mlir::OpBuilder &b, mlir::Location loc,
294 mlir::OperationState &result) {
295 mlir::OpBuilder::InsertionGuard guard(b);
298 if (needsTerminate) {
299 mlir::Block *terminateBlock = b.createBlock(
300 result.addRegion(), {}, {ehTokenTy}, {loc});
301 cir::EhTerminateOp::create(b, loc, terminateBlock->getArgument(0));
305 mlir::Block *filterBlock = b.createBlock(
306 result.addRegion(), {}, {ehTokenTy}, {loc});
308 cir::UnreachableOp::create(b, loc);
310 cir::ResumeOp::create(b, loc, filterBlock->getArgument(0));
312 mlir::Block *unexpectedBlock = b.createBlock(
313 result.addRegion(), {}, {ehTokenTy}, {loc});
314 cir::EhUnexpectedOp::create(b, loc, unexpectedBlock->getArgument(0));
318 if (needsTerminate) {
322 handlerAttrs.push_back(cir::CatchAllAttr::get(&
getMLIRContext()));
324 handlerAttrs.push_back(cir::EhFilterAttr::get(
326 handlerAttrs.push_back(cir::EhUnexpectedAttr::get(&
getMLIRContext()));
332 builder.setInsertionPointToEnd(&
ehSpecTryOp.getTryRegion().front());
344 mlir::Block *bodyExit = &tryOp.getTryRegion().back();
345 if (bodyExit->empty() ||
346 !bodyExit->back().hasTrait<mlir::OpTrait::IsTerminator>()) {
347 mlir::OpBuilder::InsertionGuard guard(builder);
348 builder.setInsertionPointToEnd(bodyExit);
349 builder.createYield(tryOp.getLoc());
353 builder.setInsertionPointAfter(tryOp);
358 if (
cgm.getLangOpts().OpenMPIsTargetDevice &&
359 (triple.isNVPTX() || triple.isAMDGCN())) {
360 cgm.errorNYI(
"emitCXXThrowExpr OpenMP with NVPTX or AMDGCN Triples");
365 QualType throwType = subExpr->getType();
367 cgm.errorNYI(
"emitCXXThrowExpr ObjCObjectPointerType");
371 cgm.getCXXABI().emitThrow(*
this, e);
375 cgm.getCXXABI().emitRethrow(*
this,
true);
415 QualType caughtType =
cgm.getASTContext().getUnqualifiedArrayType(
418 cgm.errorNYI(
"addCatchHandlerAttr: caughtType ObjCObjectPointerType");
424 handlerAttrs.push_back(typeInfo.
rtti);
427 handlerAttrs.push_back(cir::CatchAllAttr::get(&
getMLIRContext()));
433 CallEndCatch(mlir::Value catchToken) : catchToken(catchToken) {}
434 mlir::Value catchToken;
445 mlir::Type exnPtrTy) {
446 auto catchTokenTy = cir::CatchTokenType::get(cgf.
getBuilder().getContext());
447 auto beginCatch = cir::BeginCatchOp::create(cgf.
getBuilder(),
449 catchTokenTy, exnPtrTy, ehToken);
452 beginCatch.getCatchToken());
454 return beginCatch.getExnPtr();
467 cir::PointerType paramAddrType,
469 mlir::Location loc = cgf.
getLoc(clangLoc);
475 assert(copyExpr &&
"non-trivial copy expects a copy expression");
478 llvm::raw_svector_ostream thunkNameStream(thunkName);
479 thunkNameStream <<
"__clang_cir_catch_copy_";
481 catchParam.
getType(), thunkNameStream);
486 mlir::Type voidTy = cir::VoidType::get(builder.getContext());
487 auto thunkTy = cir::FuncType::get({paramAddrType, paramAddrType}, voidTy,
490 mlir::OpBuilder::InsertionGuard guard(builder);
491 builder.setInsertionPointToEnd(mod.getBody());
492 cir::FuncOp thunk = cir::FuncOp::create(builder, loc, thunkName, thunkTy);
494 thunk.setLinkage(cir::GlobalLinkageKind::LinkOnceODRLinkage);
495 thunk.setGlobalVisibility(cir::VisibilityKind::Hidden);
496 thunk->setAttr(cir::CIRDialect::getCatchCopyThunkAttrName(),
497 builder.getUnitAttr());
499 mlir::Block *entry = thunk.addEntryBlock();
500 builder.setInsertionPointToStart(entry);
508 subCgf.
curFn = thunk;
535 cir::ReturnOp::create(builder, loc);
542 mlir::Value ehToken,
const VarDecl &catchParam,
546 cir::InitCatchKind
kind;
547 bool shouldInitFromExnDirectly =
false;
553 if (
const PointerType *ptr = dyn_cast<PointerType>(caughtType)) {
554 shouldInitFromExnDirectly = !ptr->getPointeeType()->isRecordType();
556 kind = cir::InitCatchKind::Reference;
562 kind = !copyExpr ? cir::InitCatchKind::TrivialCopy
563 : cir::InitCatchKind::NonTrivialCopy;
566 if (catchType->hasPointerRepresentation()) {
570 kind = cir::InitCatchKind::Objc;
576 kind = cir::InitCatchKind::Pointer;
580 kind = cir::InitCatchKind::Scalar;
586 Address paramAddr = var.getAllocatedAddress();
587 mlir::Location mloc = cgf.
getLoc(loc);
589 if (
kind == cir::InitCatchKind::NonTrivialCopy ||
590 (
kind == cir::InitCatchKind::Reference && shouldInitFromExnDirectly)) {
596 mlir::FlatSymbolRefAttr copyFun{};
597 if (
kind == cir::InitCatchKind::NonTrivialCopy) {
599 mlir::cast<cir::PointerType>(paramAddr.
getPointer().getType());
602 copyFun = mlir::FlatSymbolRefAttr::get(thunk.getSymNameAttr());
605 cir::ConstructCatchParamOp::create(builder, mloc, ehToken,
610 cir::InitCatchParamOp::create(builder, mloc, exnPtr, paramAddr.
getPointer(),
618 mlir::Value ehToken) {
650 mlir::OpBuilder::InsertPoint scopeIP;
651 cir::ScopeOp::create(
653 [&](mlir::OpBuilder &b, mlir::Location loc) {
654 scopeIP = builder.saveInsertionPoint();
658 auto funcOp = mlir::cast<cir::FuncOp>(
curFn);
659 if (!funcOp.getPersonality())
662 mlir::OpBuilder::InsertionGuard guard(builder);
663 builder.restoreInsertionPoint(scopeIP);
668 const bool isTargetDevice =
669 (
cgm.getLangOpts().OpenMPIsTargetDevice && (t.isNVPTX() || t.isAMDGCN()));
670 if (isTargetDevice) {
671 cgm.errorNYI(
"emitCXXTryStmt: OpenMP target region offloaded to GPU");
672 return mlir::success();
679 builder.getInsertionBlock()};
682 cgm.errorNYI(
"enterCXXTryStmt: EHAsynch");
683 return mlir::failure();
687 mlir::LogicalResult tryRes = mlir::success();
688 auto tryOp = cir::TryOp::create(
691 [&](mlir::OpBuilder &b, mlir::Location loc) {
696 if (bodyCallback(*this).failed())
697 tryRes = mlir::failure();
699 if (!builder.getBlock()->mightHaveTerminator() ||
700 !builder.getBlock()->getTerminator())
701 cir::YieldOp::create(builder, loc);
704 [&](mlir::OpBuilder &b, mlir::Location loc,
705 mlir::OperationState &result) {
706 mlir::OpBuilder::InsertionGuard guard(b);
707 bool hasCatchAll =
false;
710 for (
unsigned i = 0; i != numHandlers; ++i) {
714 mlir::Region *region = result.addRegion();
715 builder.createBlock(region, {}, {ehTokenTy}, {loc});
720 mlir::Region *region = result.addRegion();
721 mlir::Block *unwindBlock =
722 builder.createBlock(region, {}, {ehTokenTy}, {loc});
723 cir::ResumeOp::create(builder, loc, unwindBlock->getArgument(0));
729 return mlir::failure();
732 tryOp.setHandlerTypesAttr(
739 for (
unsigned i = 0; i != numHandlers; ++i) {
741 mlir::Region *handler = &tryOp.getHandlerRegions()[i];
744 mlir::OpBuilder::InsertionGuard guard(builder);
745 builder.setInsertionPointToStart(&handler->front());
748 mlir::Value ehToken = handler->front().getArgument(0);
763 [[maybe_unused]] mlir::LogicalResult emitResult =
765 assert(emitResult.succeeded() &&
"failed to emit catch handler block");
777 mlir::Block *block = &handler->getBlocks().back();
778 if (block->empty() ||
779 !block->back().hasTrait<mlir::OpTrait::IsTerminator>()) {
780 mlir::OpBuilder::InsertionGuard guard(builder);
781 builder.setInsertionPointToEnd(block);
782 builder.createYield(handlerLoc);
786 return mlir::success();
791 return mlir::LogicalResult::success();
798 return cgf.
emitStmt(s.getTryBlock(),
true);
800 ~simpleTryBodyEmitter()
override =
default;
803 simpleTryBodyEmitter emitter{s};
819 if (!lo.Exceptions || lo.IgnoreExceptions) {
820 if (!lo.Borland && !lo.MicrosoftExt)
822 cgm.errorNYI(
"isInvokeDest: no exceptions or ignore exception");
827 if (lo.CUDA && lo.CUDAIsDevice)
830 return ehStack.requiresCatchOrCleanup();
static void emit(Program &P, llvm::SmallVectorImpl< std::byte > &Code, const T &Val, bool &Success)
Helper to write bytecode and bail out if 32-bit offsets become invalid.
static cir::FuncOp getOrCreateCopyThunk(CIRGenFunction &cgf, const VarDecl &catchParam, cir::PointerType paramAddrType, SourceLocation clangLoc)
Get or create the catch-init copy thunk for catchParam.
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 mlir::Value callBeginCatch(CIRGenFunction &cgf, mlir::Value ehToken, mlir::Type exnPtrTy)
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 void initCatchParam(CIRGenFunction &cgf, CIRGenBuilderTy &builder, mlir::Value ehToken, const VarDecl &catchParam, SourceLocation loc)
A "special initializer" callback for initializing a catch parameter during catch initialization.
static const EHPersonality & getSEHPersonalityMSVC(const llvm::Triple &triple)
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a kind
cir::PointerType getVoidPtrTy(clang::LangAS langAS=clang::LangAS::Default)
static CanQualType getCanonicalType(QualType T)
Return the canonical (structural) type corresponding to the specified potentially non-canonical type ...
mlir::Value getPointer() const
Address withElementType(CIRGenBuilderTy &builder, mlir::Type ElemTy) const
Return address with different element type, a bitcast pointer, and the same alignment.
static AggValueSlot forAddr(Address addr, clang::Qualifiers quals, IsDestructed_t isDestructed, IsAliased_t isAliased, Overlap_t mayOverlap, IsZeroed_t isZeroed=IsNotZeroed)
cir::IntType getSInt32Ty()
clang::MangleContext & getMangleContext()
Gets the mangle context.
An RAII object to set (and then clear) a mapping for an OpaqueValueExpr.
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.
static cir::TypeEvaluationKind getEvaluationKind(clang::QualType type)
Return the cir::TypeEvaluationKind of QualType type.
AutoVarEmission emitAutoVarAlloca(const clang::VarDecl &d, mlir::OpBuilder::InsertPoint ip={})
const clang::LangOptions & getLangOpts() const
const TargetInfo & getTarget() const
void addCatchHandlerAttr(const CXXCatchStmt *catchStmt, SmallVector< mlir::Attribute > &handlerAttrs)
Address makeNaturalAddressForPointer(mlir::Value ptr, QualType t, CharUnits alignment, bool forPointeeType=false, LValueBaseInfo *baseInfo=nullptr)
Construct an address with the natural alignment of T.
void emitAnyExprToExn(const Expr *e, Address addr)
LValue makeNaturalAlignAddrLValue(mlir::Value val, QualType ty)
cir::TryOp ehSpecTryOp
The cir.try wrapping a function whose exception specification has to be enforced.
void emitBeginCatch(const CXXCatchStmt *catchStmt, mlir::Value ehToken)
Begins a catch statement by initializing the catch variable and calling __cxa_begin_catch.
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.
CIRGenBuilderTy & getBuilder()
mlir::MLIRContext & getMLIRContext()
std::optional< SourceRange > currSrcLoc
Use to track source locations across nested visitor traversals.
void emitCXXThrowExpr(const CXXThrowExpr *e)
bool isCatchOrCleanupRequired()
void emitEndEHSpec(const clang::Decl *d)
Close the cir.try opened by emitStartEHSpec.
CIRGenFunction(CIRGenModule &cgm, CIRGenBuilderTy &builder, bool suppressNewContext=false)
void emitStartEHSpec(const clang::Decl *d)
Wrap the function body in a cir.try that enforces the exception specification of d: a filter handler ...
mlir::LogicalResult emitStmt(const clang::Stmt *s, bool useCurrentScope, llvm::ArrayRef< const Attr * > attrs={})
void emitAggExpr(const clang::Expr *e, AggValueSlot slot)
void emitAutoVarCleanups(const AutoVarEmission &emission)
This class organizes the cross-function state that is used while generating CIR code.
clang::ASTContext & getASTContext() const
void insertGlobalSymbol(mlir::Operation *op)
CIRGenBuilderTy & getBuilder()
cir::FuncOp lookupFuncOp(llvm::StringRef name)
O(1) lookup of a FuncOp by name in the symbol cache.
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
mlir::ModuleOp getModule() const
CIRGenCXXABI & getCXXABI() const
Information for lazily generating a cleanup.
CXXCatchStmt - This represents a C++ catch block.
SourceLocation getCatchLoc() const
Stmt * getHandlerBlock() const
SourceLocation getBeginLoc() const LLVM_READONLY
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.
CXXCatchStmt * getHandler(unsigned i)
unsigned getNumHandlers() const
SourceLocation getBeginLoc() const LLVM_READONLY
CompoundStmt * getTryBlock()
Qualifiers getQualifiers() const
Retrieve all qualifiers.
Represents the body of a CapturedStmt, and serves as its DeclContext.
static CharUnits Zero()
Zero - Construct a CharUnits quantity of zero.
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
SourceLocation getLocation() const
This represents one expression.
Represents a function declaration or definition.
bool usesSEHTry() const
Indicates the function uses __try.
SourceRange getExceptionSpecSourceRange() const
Attempt to compute an informative source range covering the function exception specification,...
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Represents a prototype with parameter type info, e.g.
ExceptionSpecificationType getExceptionSpecType() const
Get the kind of exception specification on this function.
CanThrowResult canThrow() const
Determine whether this function type has a non-throwing exception specification.
ArrayRef< QualType > exceptions() const
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
virtual void mangleCanonicalTypeName(QualType T, raw_ostream &, bool NormalizeIntegers=false)=0
Generates a unique string for an externally visible type for use with TBAA or type uniquing.
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.
static const OpaqueValueExpr * findInCopyConstruct(const Expr *expr)
Given an expression which invokes a copy constructor — i.e.
PointerType - C99 6.7.5.1 - Pointer Declarators.
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...
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
The collection of all-type qualifiers we support.
@ OCL_Strong
Assigning into this object requires the old value to be released and the new value to be retained.
@ OCL_ExplicitNone
This object can be modified without requiring retains or releases.
@ OCL_None
There is no lifetime qualification on this type.
@ OCL_Weak
Reading or writing from this object requires a barrier call.
@ OCL_Autoreleasing
Assigning into this object requires a lifetime extension.
ObjCLifetime getObjCLifetime() const
Encodes a location in the source.
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
const T * getAs() const
Member-template getAs<specific type>'.
Represents a variable declaration or definition.
const Expr * getInit() const
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
Top level wrappers for InstallAPI frontend operations.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
U cast(CodeGen::Address addr)
ExceptionSpecificationType
The various types of exception specifications that exist in C++11.
@ EST_Dynamic
throw(T1, T2)
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
const char * personalityFn
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