[clang] [CIR][WIP] Make BeginCatchOp target-independent (PR #190612)
Amr Hesham via cfe-commits
cfe-commits at lists.llvm.org
Sun Apr 19 06:41:52 PDT 2026
https://github.com/AmrDeveloper updated https://github.com/llvm/llvm-project/pull/190612
>From b9a4188f364a19ad31ee2b504c8077e34ea6ceee Mon Sep 17 00:00:00 2001
From: Amr Hesham <amr96 at programmer.net>
Date: Sun, 12 Apr 2026 17:56:43 +0200
Subject: [PATCH] [CIR] Make BeginCatchOp target-independent
---
clang/lib/CIR/CodeGen/CIRGenCXXABI.h | 4 -
clang/lib/CIR/CodeGen/CIRGenException.cpp | 180 +++++++++-
clang/lib/CIR/CodeGen/CIRGenFunction.h | 2 +
clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp | 239 -------------
.../CIR/Dialect/Transforms/EHABILowering.cpp | 50 ++-
.../CodeGen/try-catch-all-with-cleanup.cpp | 9 -
clang/test/CIR/CodeGen/try-catch.cpp | 336 +++++++++++++++---
7 files changed, 510 insertions(+), 310 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
index 614d62fda44a5..bb100f7afd929 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
+++ b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
@@ -134,10 +134,6 @@ class CIRGenCXXABI {
virtual void emitBadCastCall(CIRGenFunction &cgf, mlir::Location loc) = 0;
- virtual void emitBeginCatch(CIRGenFunction &cgf,
- const CXXCatchStmt *catchStmt,
- mlir::Value ehToken) = 0;
-
virtual mlir::Attribute getAddrOfRTTIDescriptor(mlir::Location loc,
QualType ty) = 0;
diff --git a/clang/lib/CIR/CodeGen/CIRGenException.cpp b/clang/lib/CIR/CodeGen/CIRGenException.cpp
index c80f292553a1c..7dd2a8d59199e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenException.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenException.cpp
@@ -273,6 +273,184 @@ void CIRGenFunction::addCatchHandlerAttr(
}
}
+namespace {
+/// From traditional LLVM, useful info for LLVM lowering support:
+/// A cleanup to call __cxa_end_catch. In many cases, the caught
+/// exception type lets us state definitively that the thrown exception
+/// type does not have a destructor. In particular:
+/// - Catch-alls tell us nothing, so we have to conservatively
+/// assume that the thrown exception might have a destructor.
+/// - Catches by reference behave according to their base types.
+/// - Catches of non-record types will only trigger for exceptions
+/// of non-record types, which never have destructors.
+/// - Catches of record types can trigger for arbitrary subclasses
+/// of the caught type, so we have to assume the actual thrown
+/// exception type might have a throwing destructor, even if the
+/// caught type's destructor is trivial or nothrow.
+struct CallEndCatch final : EHScopeStack::Cleanup {
+ CallEndCatch(bool mightThrow, mlir::Value catchToken)
+ : mightThrow(mightThrow), catchToken(catchToken) {}
+ bool mightThrow;
+ mlir::Value catchToken;
+
+ void emit(CIRGenFunction &cgf, Flags flags) override {
+ // Traditional LLVM codegen would emit a call to __cxa_end_catch
+ // here. For CIR, just let it pass since the cleanup is going
+ // to be emitted on a later pass when lowering the catch region.
+ // CGF.EmitRuntimeCallOrTryCall(getEndCatchFn(CGF.CGM));
+ cir::EndCatchOp::create(cgf.getBuilder(), *cgf.currSrcLoc, catchToken);
+ cir::YieldOp::create(cgf.getBuilder(), *cgf.currSrcLoc);
+ }
+};
+} // namespace
+
+static mlir::Value callBeginCatch(CIRGenFunction &cgf, mlir::Value ehToken,
+ mlir::Type exnPtrTy, bool endMightThrow) {
+ auto catchTokenTy = cir::CatchTokenType::get(cgf.getBuilder().getContext());
+ auto beginCatch = cir::BeginCatchOp::create(cgf.getBuilder(),
+ cgf.getBuilder().getUnknownLoc(),
+ catchTokenTy, exnPtrTy, ehToken);
+
+ cgf.ehStack.pushCleanup<CallEndCatch>(
+ NormalAndEHCleanup,
+ endMightThrow && !cgf.cgm.getLangOpts().AssumeNothrowExceptionDtor,
+ beginCatch.getCatchToken());
+
+ return beginCatch.getExnPtr();
+}
+
+/// A "special initializer" callback for initializing a catch
+/// parameter during catch initialization.
+static void initCatchParam(CIRGenFunction &cgf, mlir::Value ehToken,
+ const VarDecl &catchParam, Address paramAddr,
+ SourceLocation loc) {
+ CIRGenBuilderTy builder = cgf.getBuilder();
+ CanQualType catchType =
+ cgf.cgm.getASTContext().getCanonicalType(catchParam.getType());
+ mlir::Type cirCatchTy = cgf.convertTypeForMem(catchType);
+ mlir::Type exnPtrTy = builder.getPointerTo(cirCatchTy);
+ CharUnits caughtExnAlignment = cgf.getPointerAlign();
+
+ // If we're catching by reference, we can just cast the object
+ // pointer to the appropriate pointer.
+ if (isa<ReferenceType>(catchType)) {
+ QualType caughtType = cast<ReferenceType>(catchType)->getPointeeType();
+ // We have no way to tell the personality function that we're
+ // catching by reference, so if we're catching a pointer,
+ // __cxa_begin_catch will actually return that pointer by value.
+ if (const PointerType *pt = dyn_cast<PointerType>(caughtType)) {
+ QualType pointeeType = pt->getPointeeType();
+ // When catching by reference, generally we should just ignore
+ // this by-value pointer and use the exception object instead.
+ if (!pointeeType->isRecordType()) {
+ cgf.cgm.errorNYI(loc,
+ "initCatchParam: catching a pointer of non-record");
+ return;
+ }
+ }
+
+ bool endCatchMightThrow = caughtType->isRecordType();
+ mlir::Value exnPtr =
+ callBeginCatch(cgf, ehToken, exnPtrTy, endCatchMightThrow);
+ Address exnPtrAddr = Address(exnPtr, caughtExnAlignment);
+ cgf.setAddrOfLocalVar(&catchParam, exnPtrAddr);
+ return;
+ }
+
+ // Scalars and complexes.
+ cir::TypeEvaluationKind tek = cgf.getEvaluationKind(catchType);
+ if (tek != cir::TEK_Aggregate) {
+ // Notes for LLVM lowering:
+ // If the catch type is a pointer type, __cxa_begin_catch returns
+ // the pointer by value.
+ if (catchType->hasPointerRepresentation()) {
+ switch (catchType.getQualifiers().getObjCLifetime()) {
+ case Qualifiers::OCL_Strong:
+ cgf.cgm.errorNYI(loc,
+ "initCatchParam: PointerRepresentation OCL_Strong");
+ return;
+
+ case Qualifiers::OCL_ExplicitNone:
+ case Qualifiers::OCL_Autoreleasing:
+ cgf.cgm.errorNYI(loc, "initCatchParam: PointerRepresentation "
+ "OCL_ExplicitNone & OCL_Autoreleasing");
+ return;
+
+ case Qualifiers::OCL_None:
+ break;
+
+ case Qualifiers::OCL_Weak:
+ cgf.cgm.errorNYI(loc, "initCatchParam: PointerRepresentation OCL_Weak");
+ return;
+ }
+ }
+
+ // Otherwise, it returns a pointer into the exception object.
+ mlir::Value exnPtr = callBeginCatch(cgf, ehToken, exnPtrTy,
+ /*endMightThrow=*/false);
+ Address exnPtrAddr = Address(exnPtr, caughtExnAlignment);
+ cgf.setAddrOfLocalVar(&catchParam, exnPtrAddr);
+ return;
+ }
+
+ assert(isa<RecordType>(catchType) && "unexpected catch type!");
+ auto *catchRD = catchType->getAsCXXRecordDecl();
+ caughtExnAlignment = cgf.cgm.getClassPointerAlignment(catchRD);
+
+ // Check for a copy expression. If we don't have a copy expression,
+ // that means a trivial copy is okay.
+ const Expr *copyExpr = catchParam.getInit();
+ if (!copyExpr) {
+ mlir::Value exnPtr =
+ callBeginCatch(cgf, ehToken, exnPtrTy, /*endMightThrow=*/true);
+ Address exnPtrAddr = Address(exnPtr, caughtExnAlignment);
+ cgf.setAddrOfLocalVar(&catchParam, exnPtrAddr);
+ return;
+ }
+
+ cgf.cgm.errorNYI(loc, "initCatchParam: cir::TEK_Aggregate non-trivial copy");
+}
+
+/// Begins a catch statement by initializing the catch variable and
+/// calling __cxa_begin_catch.
+void CIRGenFunction::emitBeginCatch(const CXXCatchStmt *catchStmt,
+ mlir::Value ehToken) {
+ // We have to be very careful with the ordering of cleanups here:
+ // C++ [except.throw]p4:
+ // The destruction [of the exception temporary] occurs
+ // immediately after the destruction of the object declared in
+ // the exception-declaration in the handler.
+ //
+ // So the precise ordering is:
+ // 1. Construct catch variable.
+ // 2. __cxa_begin_catch
+ // 3. Enter __cxa_end_catch cleanup
+ // 4. Enter dtor cleanup
+ //
+ // We do this by using a slightly abnormal initialization process.
+ // Delegation sequence:
+ // - ExitCXXTryStmt opens a RunCleanupsScope
+ // - EmitAutoVarAlloca creates the variable and debug info
+ // - InitCatchParam initializes the variable from the exception
+ // - CallBeginCatch calls __cxa_begin_catch
+ // - CallBeginCatch enters the __cxa_end_catch cleanup
+ // - EmitAutoVarCleanups enters the variable destructor cleanup
+ // - EmitCXXTryStmt emits the code for the catch body
+ // - EmitCXXTryStmt close the RunCleanupsScope
+ VarDecl *catchParam = catchStmt->getExceptionDecl();
+ if (!catchParam) {
+ callBeginCatch(*this, ehToken, builder.getVoidPtrTy(),
+ /*endMightThrow=*/true);
+ return;
+ }
+
+ // Emit the local. Make sure the alloca's superseed the current scope, since
+ // these are going to be consumed by `cir.catch`, which is not within the
+ // current scope.
+ initCatchParam(*this, ehToken, *catchParam, Address::invalid(),
+ catchStmt->getBeginLoc());
+}
+
mlir::LogicalResult
CIRGenFunction::emitCXXTryStmt(const CXXTryStmt &s,
cxxTryBodyEmitter &bodyCallback) {
@@ -384,7 +562,7 @@ CIRGenFunction::emitCXXTryStmt(const CXXTryStmt &s,
// Initialize the catch variable.
// TODO(cir): Move this out of CXXABI.
assert(!cir::MissingFeatures::currentFuncletPad());
- cgm.getCXXABI().emitBeginCatch(*this, catchStmt, ehToken);
+ emitBeginCatch(catchStmt, ehToken);
// Emit the PGO counter increment.
assert(!cir::MissingFeatures::incrementProfileCounter());
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 7cbea29a7c3f9..0e6b23e5c23e2 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -1785,6 +1785,8 @@ class CIRGenFunction : public CIRGenTypeCache {
virtual ~cxxTryBodyEmitter() = default;
};
+ void emitBeginCatch(const CXXCatchStmt *catchStmt, mlir::Value ehToken);
+
mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s,
cxxTryBodyEmitter &bodyCallback);
mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s);
diff --git a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
index c398e6183d91c..26892db694f64 100644
--- a/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenItaniumCXXABI.cpp
@@ -82,9 +82,6 @@ class CIRGenItaniumCXXABI : public CIRGenCXXABI {
void emitRethrow(CIRGenFunction &cgf, bool isNoReturn) override;
void emitThrow(CIRGenFunction &cgf, const CXXThrowExpr *e) override;
- void emitBeginCatch(CIRGenFunction &cgf, const CXXCatchStmt *catchStmt,
- mlir::Value ehToken) override;
-
bool useThunkForDtorVariant(const CXXDestructorDecl *dtor,
CXXDtorType dt) const override {
// Itanium does not emit any destructor variant as an inline thunk.
@@ -2490,242 +2487,6 @@ Address CIRGenItaniumCXXABI::initializeArrayCookie(CIRGenFunction &cgf,
return Address(finalPtr, newPtr.getElementType(), finalAlignment);
}
-namespace {
-/// From traditional LLVM, useful info for LLVM lowering support:
-/// A cleanup to call __cxa_end_catch. In many cases, the caught
-/// exception type lets us state definitively that the thrown exception
-/// type does not have a destructor. In particular:
-/// - Catch-alls tell us nothing, so we have to conservatively
-/// assume that the thrown exception might have a destructor.
-/// - Catches by reference behave according to their base types.
-/// - Catches of non-record types will only trigger for exceptions
-/// of non-record types, which never have destructors.
-/// - Catches of record types can trigger for arbitrary subclasses
-/// of the caught type, so we have to assume the actual thrown
-/// exception type might have a throwing destructor, even if the
-/// caught type's destructor is trivial or nothrow.
-struct CallEndCatch final : EHScopeStack::Cleanup {
- CallEndCatch(bool mightThrow, mlir::Value catchToken)
- : mightThrow(mightThrow), catchToken(catchToken) {}
- bool mightThrow;
- mlir::Value catchToken;
-
- void emit(CIRGenFunction &cgf, Flags flags) override {
- // Traditional LLVM codegen would emit a call to __cxa_end_catch
- // here. For CIR, just let it pass since the cleanup is going
- // to be emitted on a later pass when lowering the catch region.
- // CGF.EmitRuntimeCallOrTryCall(getEndCatchFn(CGF.CGM));
- cir::EndCatchOp::create(cgf.getBuilder(), *cgf.currSrcLoc, catchToken);
- cir::YieldOp::create(cgf.getBuilder(), *cgf.currSrcLoc);
- }
-};
-} // namespace
-
-static mlir::Value callBeginCatch(CIRGenFunction &cgf, mlir::Value ehToken,
- mlir::Type exnPtrTy, bool endMightThrow) {
- auto catchTokenTy = cir::CatchTokenType::get(cgf.getBuilder().getContext());
- auto beginCatch = cir::BeginCatchOp::create(cgf.getBuilder(),
- cgf.getBuilder().getUnknownLoc(),
- catchTokenTy, exnPtrTy, ehToken);
-
- cgf.ehStack.pushCleanup<CallEndCatch>(
- NormalAndEHCleanup,
- endMightThrow && !cgf.cgm.getLangOpts().AssumeNothrowExceptionDtor,
- beginCatch.getCatchToken());
-
- return beginCatch.getExnPtr();
-}
-
-/// A "special initializer" callback for initializing a catch
-/// parameter during catch initialization.
-static void initCatchParam(CIRGenFunction &cgf, mlir::Value ehToken,
- const VarDecl &catchParam, Address paramAddr,
- SourceLocation loc) {
- CanQualType catchType =
- cgf.cgm.getASTContext().getCanonicalType(catchParam.getType());
- mlir::Type cirCatchTy = cgf.convertTypeForMem(catchType);
-
- // If we're catching by reference, we can just cast the object
- // pointer to the appropriate pointer.
- if (isa<ReferenceType>(catchType)) {
- QualType caughtType = cast<ReferenceType>(catchType)->getPointeeType();
- bool endCatchMightThrow = caughtType->isRecordType();
-
- mlir::Value adjustedExn =
- callBeginCatch(cgf, ehToken, cirCatchTy, endCatchMightThrow);
-
- // We have no way to tell the personality function that we're
- // catching by reference, so if we're catching a pointer,
- // __cxa_begin_catch will actually return that pointer by value.
- if (const PointerType *pt = dyn_cast<PointerType>(caughtType)) {
- QualType pointeeType = pt->getPointeeType();
- // When catching by reference, generally we should just ignore
- // this by-value pointer and use the exception object instead.
- if (!pointeeType->isRecordType()) {
- cgf.cgm.errorNYI(loc,
- "initCatchParam: catching a pointer of non-record");
- } else {
- // Pull the pointer for the reference type off.
- mlir::Type ptrTy = cgf.convertTypeForMem(caughtType);
-
- // Create the temporary and write the adjusted pointer into it.
- Address exnPtrTmp = cgf.createTempAlloca(
- ptrTy, cgf.getPointerAlign(), cgf.getLoc(loc), "exn.byref.tmp");
- mlir::Value casted = cgf.getBuilder().createBitcast(adjustedExn, ptrTy);
- cgf.getBuilder().createStore(cgf.getLoc(loc), casted, exnPtrTmp);
-
- // Bind the reference to the temporary.
- adjustedExn = exnPtrTmp.emitRawPointer();
- }
- }
-
- mlir::Value exnCast =
- cgf.getBuilder().createBitcast(adjustedExn, cirCatchTy);
- cgf.getBuilder().createStore(cgf.getLoc(loc), exnCast, paramAddr);
- return;
- }
-
- // Scalars and complexes.
- cir::TypeEvaluationKind tek = cgf.getEvaluationKind(catchType);
- if (tek != cir::TEK_Aggregate) {
- // Notes for LLVM lowering:
- // If the catch type is a pointer type, __cxa_begin_catch returns
- // the pointer by value.
- if (catchType->hasPointerRepresentation()) {
- mlir::Value catchParam =
- callBeginCatch(cgf, ehToken, cirCatchTy, /*endMightThrow=*/false);
- switch (catchType.getQualifiers().getObjCLifetime()) {
- case Qualifiers::OCL_Strong:
- cgf.cgm.errorNYI(loc,
- "initCatchParam: PointerRepresentation OCL_Strong");
- return;
-
- case Qualifiers::OCL_ExplicitNone:
- case Qualifiers::OCL_Autoreleasing:
- cgf.cgm.errorNYI(loc, "initCatchParam: PointerRepresentation "
- "OCL_ExplicitNone & OCL_Autoreleasing");
- return;
-
- case Qualifiers::OCL_None:
- cgf.getBuilder().createStore(cgf.getLoc(loc), catchParam, paramAddr);
- return;
-
- case Qualifiers::OCL_Weak:
- cgf.cgm.errorNYI(loc, "initCatchParam: PointerRepresentation OCL_Weak");
- return;
- }
-
- llvm_unreachable("bad ownership qualifier!");
- }
-
- // Otherwise, it returns a pointer into the exception object.
- mlir::Type cirCatchTy = cgf.convertTypeForMem(catchType);
- mlir::Value catchParam =
- callBeginCatch(cgf, ehToken, cgf.getBuilder().getPointerTo(cirCatchTy),
- /*endMightThrow=*/false);
- LValue srcLV = cgf.makeNaturalAlignAddrLValue(catchParam, catchType);
- LValue destLV = cgf.makeAddrLValue(paramAddr, catchType);
- switch (tek) {
- case cir::TEK_Complex: {
- mlir::Value load = cgf.emitLoadOfComplex(srcLV, loc);
- cgf.emitStoreOfComplex(cgf.getLoc(loc), load, destLV, /*isInit=*/true);
- return;
- }
- case cir::TEK_Scalar: {
- mlir::Value exnLoad = cgf.emitLoadOfScalar(srcLV, loc);
- cgf.emitStoreOfScalar(exnLoad, destLV, /*isInit=*/true);
- return;
- }
- case cir::TEK_Aggregate:
- llvm_unreachable("evaluation kind filtered out!");
- }
-
- llvm_unreachable("bad evaluation kind");
- }
-
- assert(isa<RecordType>(catchType) && "unexpected catch type!");
- auto *catchRD = catchType->getAsCXXRecordDecl();
- CharUnits caughtExnAlignment = cgf.cgm.getClassPointerAlignment(catchRD);
-
- // Check for a copy expression. If we don't have a copy expression,
- // that means a trivial copy is okay.
- const Expr *copyExpr = catchParam.getInit();
- if (!copyExpr) {
- mlir::Type cirCatchPtrTy = cgf.getBuilder().getPointerTo(cirCatchTy);
- mlir::Value rawAdjustedExn =
- callBeginCatch(cgf, ehToken, cirCatchPtrTy, /*endMightThrow=*/true);
- Address adjustedExn(rawAdjustedExn, cirCatchTy, caughtExnAlignment);
- LValue dest = cgf.makeAddrLValue(paramAddr, catchType);
- LValue src = cgf.makeAddrLValue(adjustedExn, catchType);
- cgf.emitAggregateCopy(dest, src, catchType, AggValueSlot::DoesNotOverlap);
- return;
- }
-
- cgf.cgm.errorNYI(loc, "initCatchParam: cir::TEK_Aggregate non-trivial copy");
-}
-
-/// Begins a catch statement by initializing the catch variable and
-/// calling __cxa_begin_catch.
-void CIRGenItaniumCXXABI::emitBeginCatch(CIRGenFunction &cgf,
- const CXXCatchStmt *catchStmt,
- mlir::Value ehToken) {
- // We have to be very careful with the ordering of cleanups here:
- // C++ [except.throw]p4:
- // The destruction [of the exception temporary] occurs
- // immediately after the destruction of the object declared in
- // the exception-declaration in the handler.
- //
- // So the precise ordering is:
- // 1. Construct catch variable.
- // 2. __cxa_begin_catch
- // 3. Enter __cxa_end_catch cleanup
- // 4. Enter dtor cleanup
- //
- // We do this by using a slightly abnormal initialization process.
- // Delegation sequence:
- // - ExitCXXTryStmt opens a RunCleanupsScope
- // - EmitAutoVarAlloca creates the variable and debug info
- // - InitCatchParam initializes the variable from the exception
- // - CallBeginCatch calls __cxa_begin_catch
- // - CallBeginCatch enters the __cxa_end_catch cleanup
- // - EmitAutoVarCleanups enters the variable destructor cleanup
- // - EmitCXXTryStmt emits the code for the catch body
- // - EmitCXXTryStmt close the RunCleanupsScope
-
- VarDecl *catchParam = catchStmt->getExceptionDecl();
- if (!catchParam) {
- callBeginCatch(cgf, ehToken, cgf.getBuilder().getVoidPtrTy(),
- /*endMightThrow=*/true);
- return;
- }
-
- auto getCatchParamAllocaIP = [&]() {
- cir::CIRBaseBuilderTy::InsertPoint currIns =
- cgf.getBuilder().saveInsertionPoint();
- mlir::Operation *currParent = currIns.getBlock()->getParentOp();
-
- mlir::Block *insertBlock = nullptr;
- if (auto scopeOp = currParent->getParentOfType<cir::ScopeOp>()) {
- insertBlock = &scopeOp.getScopeRegion().getBlocks().back();
- } else if (auto fnOp = currParent->getParentOfType<cir::FuncOp>()) {
- insertBlock = &fnOp.getRegion().getBlocks().back();
- } else {
- llvm_unreachable("unknown outermost scope-like parent");
- }
- return cgf.getBuilder().getBestAllocaInsertPoint(insertBlock);
- };
-
- // Emit the local. Make sure the alloca's superseed the current scope, since
- // these are going to be consumed by `cir.catch`, which is not within the
- // current scope.
-
- CIRGenFunction::AutoVarEmission var =
- cgf.emitAutoVarAlloca(*catchParam, getCatchParamAllocaIP());
- initCatchParam(cgf, ehToken, *catchParam, var.getObjectAddress(cgf),
- catchStmt->getBeginLoc());
- cgf.emitAutoVarCleanups(var);
-}
-
bool CIRGenItaniumCXXABI::hasAnyUnusedVirtualInlineFunction(
const CXXRecordDecl *rd) const {
const auto &vtableLayout = cgm.getItaniumVTableContext().getVTableLayout(rd);
diff --git a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
index abdc32951f857..e9b11595163b5 100644
--- a/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/EHABILowering.cpp
@@ -281,6 +281,47 @@ mlir::LogicalResult ItaniumEHLowering::lowerFunc(cir::FuncOp funcOp) {
return mlir::success();
}
+static mlir::Value initCatchParam(mlir::OpBuilder &builder,
+ cir::BeginCatchOp op,
+ mlir::Value beginCatchCall) {
+ mlir::Value result = beginCatchCall;
+ mlir::Type expectedPtrType = op.getExnPtr().getType();
+
+ auto exceptionType =
+ mlir::cast<cir::PointerType>(expectedPtrType).getPointee();
+
+ if (auto exnPointeeType = mlir::dyn_cast<cir::PointerType>(exceptionType)) {
+ if (auto exnPointeePtrType =
+ mlir::dyn_cast<cir::PointerType>(exnPointeeType.getPointee())) {
+ if (mlir::isa<cir::RecordType>(exnPointeePtrType.getPointee())) {
+ auto parentFunc = op->getParentOfType<cir::FuncOp>();
+ mlir::Block *entryBlock = &parentFunc.getRegion().front();
+
+ mlir::Value exnPtrTmp;
+ {
+ mlir::OpBuilder::InsertionGuard guard(builder);
+ builder.setInsertionPointToStart(entryBlock);
+ exnPtrTmp = cir::AllocaOp::create(
+ builder, op->getLoc(), expectedPtrType, exceptionType,
+ "exn.byref.tmp", builder.getI64IntegerAttr(8));
+ }
+
+ result = cir::CastOp::create(builder, op.getLoc(), exceptionType,
+ cir::CastKind::bitcast, result);
+
+ cir::StoreOp::create(builder, op.getLoc(), result, exnPtrTmp, {}, {},
+ {}, {});
+ result = exnPtrTmp;
+ }
+ }
+ }
+
+ return result.getType() == expectedPtrType
+ ? result
+ : cir::CastOp::create(builder, op->getLoc(), expectedPtrType,
+ cir::CastKind::bitcast, result);
+}
+
/// Lower all EH operations connected to a single cir.eh.initiate.
///
/// The cir.eh.initiate is the root of a token graph. The token it produces
@@ -394,13 +435,8 @@ void ItaniumEHLowering::lowerEhInitiate(
auto callOp = cir::CallOp::create(
builder, op.getLoc(), mlir::FlatSymbolRefAttr::get(beginCatchFunc),
u8PtrType, mlir::ValueRange{exnPtr});
- mlir::Value castResult = callOp.getResult();
- mlir::Type expectedPtrType = op.getExnPtr().getType();
- if (castResult.getType() != expectedPtrType)
- castResult =
- cir::CastOp::create(builder, op.getLoc(), expectedPtrType,
- cir::CastKind::bitcast, callOp.getResult());
- op.getExnPtr().replaceAllUsesWith(castResult);
+ mlir::Value result = initCatchParam(builder, op, callOp.getResult());
+ op.getExnPtr().replaceAllUsesWith(result);
op.erase();
} else if (auto op = mlir::dyn_cast<cir::EhDispatchOp>(user)) {
// Read catch types from the dispatch and set them on the inflight op.
diff --git a/clang/test/CIR/CodeGen/try-catch-all-with-cleanup.cpp b/clang/test/CIR/CodeGen/try-catch-all-with-cleanup.cpp
index 3827275bfc1be..5e1cc064e5ea5 100644
--- a/clang/test/CIR/CodeGen/try-catch-all-with-cleanup.cpp
+++ b/clang/test/CIR/CodeGen/try-catch-all-with-cleanup.cpp
@@ -149,7 +149,6 @@ void test_catch_all_and_specific_with_cleanup() {
// CIR-LABEL: cir.func {{.*}} @_Z40test_catch_all_and_specific_with_cleanupv()
// CIR: cir.scope {
// CIR: %[[S:.*]] = cir.alloca !rec_S, !cir.ptr<!rec_S>, ["s", init]
-// CIR: %[[E:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["e"]
// CIR: cir.try {
// CIR: cir.call @_ZN1SC1Ev(%[[S]])
// CIR: cir.cleanup.scope {
@@ -163,8 +162,6 @@ void test_catch_all_and_specific_with_cleanup() {
// CIR: } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] (%{{.*}}: !cir.eh_token {{.*}}) {
// CIR: %{{.*}}, %[[EXN:.*]] = cir.begin_catch %{{.*}} : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>)
// CIR: cir.cleanup.scope {
-// CIR: cir.load{{.*}} %[[EXN]] : !cir.ptr<!s32i>, !s32i
-// CIR: cir.store{{.*}} %{{.*}}, %[[E]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.yield
// CIR: } cleanup all {
// CIR: cir.end_catch %{{.*}} : !cir.catch_token
@@ -186,7 +183,6 @@ void test_catch_all_and_specific_with_cleanup() {
// CIR-FLAT-LABEL: cir.func {{.*}} @_Z40test_catch_all_and_specific_with_cleanupv()
//
// CIR-FLAT: %[[S:.*]] = cir.alloca !rec_S
-// CIR-FLAT: %[[E:.*]] = cir.alloca !s32i
//
// Ctor may throw; unwinds directly to the dispatch (no cleanup needed yet).
// CIR-FLAT: cir.try_call @_ZN1SC1Ev(%[[S]]) ^[[AFTER_CTOR:bb[0-9]+]], ^[[CTOR_UNWIND:bb[0-9]+]]
@@ -227,8 +223,6 @@ void test_catch_all_and_specific_with_cleanup() {
// Catch (int): bind e, end_catch, merge to return.
// CIR-FLAT: ^[[CATCH_INT]](%{{.*}}: !cir.eh_token):
// CIR-FLAT: %{{.*}}, %[[EXN_PTR:.*]] = cir.begin_catch %{{.*}} : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>)
-// CIR-FLAT: cir.load{{.*}} %[[EXN_PTR]] : !cir.ptr<!s32i>, !s32i
-// CIR-FLAT: cir.store{{.*}} %{{.*}}, %[[E]] : !s32i, !cir.ptr<!s32i>
// CIR-FLAT: cir.end_catch %{{.*}} : !cir.catch_token
// CIR-FLAT: cir.br ^{{.*}}
//
@@ -248,7 +242,6 @@ void test_catch_all_and_specific_with_cleanup() {
// LLVM-LABEL: define {{.*}} void @_Z40test_catch_all_and_specific_with_cleanupv()
// LLVM-SAME: personality ptr @__gxx_personality_v0
// LLVM: %[[S:.*]] = alloca %struct.S
-// LLVM: %[[E:.*]] = alloca i32
// LLVM: invoke void @_ZN1SC1Ev({{.*}}%[[S]])
// LLVM: to label %[[AFTER_CTOR:.*]] unwind label %[[CTOR_LP:.*]]
// LLVM: [[AFTER_CTOR]]:
@@ -269,8 +262,6 @@ void test_catch_all_and_specific_with_cleanup() {
// LLVM: icmp eq i32 {{.*}}, {{.*}}
// LLVM: {{.*}}:
// LLVM: call ptr @__cxa_begin_catch
-// LLVM: load i32, ptr {{.*}}
-// LLVM: store i32 {{.*}}, ptr %[[E]]
// LLVM: call void @__cxa_end_catch()
// LLVM: {{.*}}:
// LLVM: call ptr @__cxa_begin_catch
diff --git a/clang/test/CIR/CodeGen/try-catch.cpp b/clang/test/CIR/CodeGen/try-catch.cpp
index fd8b9294c9f92..6c8942e4fab2c 100644
--- a/clang/test/CIR/CodeGen/try-catch.cpp
+++ b/clang/test/CIR/CodeGen/try-catch.cpp
@@ -127,6 +127,7 @@ void try_catch_with_alloca() {
}
}
+// CIR: cir.func {{.*}} @_Z21try_catch_with_allocav() personality(@__gxx_personality_v0)
// CIR: cir.scope {
// CIR: %[[A_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["a"]
// CIR: %[[B_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["b"]
@@ -213,7 +214,7 @@ void call_function_inside_try_catch_all() {
// CIR: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[EH_TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>)
// CIR: cir.cleanup.scope {
// CIR: cir.yield
-// CIR: } cleanup {{.*}} {
+// CIR: } cleanup all {
// CIR: cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token
// CIR: cir.yield
// CIR: }
@@ -291,17 +292,14 @@ void call_function_inside_try_catch_with_exception_type() {
// CIR: cir.func {{.*}} @_Z50call_function_inside_try_catch_with_exception_typev() personality(@__gxx_personality_v0)
// CIR: cir.scope {
-// CIR: %[[EXCEPTION_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["e"]
// CIR: cir.try {
// CIR: %[[CALL:.*]] = cir.call @_Z8divisionv()
// CIR: cir.yield
// CIR: } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] (%[[EH_TOKEN:.*]]: !cir.eh_token{{.*}}) {
// CIR: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[EH_TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>)
// CIR: cir.cleanup.scope {
-// CIR: %[[TMP:.*]] = cir.load {{.*}} %[[EXN_PTR]] : !cir.ptr<!s32i>, !s32i
-// CIR: cir.store {{.*}} %[[TMP]], %[[EXCEPTION_ADDR]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.yield
-// CIR: } cleanup {{.*}} {
+// CIR: } cleanup all {
// CIR: cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token
// CIR: cir.yield
// CIR: }
@@ -342,8 +340,6 @@ void call_function_inside_try_catch_with_exception_type() {
// LLVM: %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]])
// LLVM: br label %[[CATCH_BODY:.*]]
// LLVM: [[CATCH_BODY]]:
-// LLVM: %[[LOAD:.*]] = load i32, ptr %[[TOKEN]], align 4
-// LLVM: store i32 %[[LOAD]], ptr {{.*}}, align 4
// LLVM: br label %[[END_CATCH:.*]]
// LLVM: [[END_CATCH]]:
// LLVM: call void @__cxa_end_catch()
@@ -409,14 +405,12 @@ void call_function_inside_try_catch_with_ref_exception_type() {
// CIR: cir.func {{.*}} @_Z54call_function_inside_try_catch_with_ref_exception_typev() personality(@__gxx_personality_v0)
// CIR: cir.scope {
-// CIR: %[[EXCEPTION_ADDR:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["ref", const]
// CIR: cir.try {
// CIR: %[[CALL:.*]] = cir.call @_Z8divisionv()
// CIR: cir.yield
// CIR: } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] (%{{.*}}: !cir.eh_token {{.*}}) {
-// CIR: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %{{.*}} : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>)
+// CIR: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %{{.*}} : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!cir.ptr<!s32i>>)
// CIR: cir.cleanup.scope {
-// CIR: cir.store {{.*}} %[[EXN_PTR]], %[[EXCEPTION_ADDR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
// CIR: cir.yield
// CIR: } cleanup all {
// CIR: cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token
@@ -459,7 +453,6 @@ void call_function_inside_try_catch_with_ref_exception_type() {
// LLVM: %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]])
// LLVM: br label %[[CATCH_BODY:.*]]
// LLVM: [[CATCH_BODY]]:
-// LLVM: store ptr %[[TOKEN]], ptr %{{.*}}, align 8
// LLVM: br label %[[END_CATCH:.*]]
// LLVM: [[END_CATCH]]:
// LLVM: call void @__cxa_end_catch()
@@ -524,17 +517,14 @@ void call_function_inside_try_catch_with_complex_exception_type() {
// CIR: cir.func {{.*}} @_Z58call_function_inside_try_catch_with_complex_exception_typev() personality(@__gxx_personality_v0)
// CIR: cir.scope {
-// CIR: %[[EXCEPTION_ADDR:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["e"]
// CIR: cir.try {
// CIR: %[[CALL:.*]] = cir.call @_Z8divisionv()
// CIR: cir.yield
// CIR: } catch [type #cir.global_view<@_ZTICi> : !cir.ptr<!u8i>] (%[[EH_TOKEN:.*]]: !cir.eh_token{{.*}}) {
// CIR: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[EH_TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!cir.complex<!s32i>>)
// CIR: cir.cleanup.scope {
-// CIR: %[[TMP:.*]] = cir.load {{.*}} %[[EXN_PTR]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i>
-// CIR: cir.store {{.*}} %[[TMP]], %[[EXCEPTION_ADDR]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>
// CIR: cir.yield
-// CIR: } cleanup {{.*}} {
+// CIR: } cleanup all {
// CIR: cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token
// CIR: cir.yield
// CIR: }
@@ -575,8 +565,6 @@ void call_function_inside_try_catch_with_complex_exception_type() {
// LLVM: %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]])
// LLVM: br label %[[CATCH_BODY:.*]]
// LLVM: [[CATCH_BODY]]:
-// LLVM: %[[LOAD:.*]] = load { i32, i32 }, ptr %[[TOKEN]], align 4
-// LLVM: store { i32, i32 } %[[LOAD]], ptr {{.*}}, align 4
// LLVM: br label %[[END_CATCH:.*]]
// LLVM: [[END_CATCH]]:
// LLVM: call void @__cxa_end_catch()
@@ -648,16 +636,14 @@ void call_function_inside_try_catch_with_array_exception_type() {
// CIR: cir.func {{.*}} @_Z56call_function_inside_try_catch_with_array_exception_typev() personality(@__gxx_personality_v0)
// CIR: cir.scope {
-// CIR: %[[E_ADDR:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["e"]
// CIR: cir.try {
// CIR: %[[CALL:.*]] = cir.call @_Z8divisionv()
// CIR: cir.yield
// CIR: } catch [type #cir.global_view<@_ZTIPi> : !cir.ptr<!u8i>] (%[[EH_TOKEN:.*]]: !cir.eh_token{{.*}}) {
-// CIR: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[EH_TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>)
+// CIR: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[EH_TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!cir.ptr<!s32i>>)
// CIR: cir.cleanup.scope {
-// CIR: cir.store {{.*}} %[[EXN_PTR]], %[[E_ADDR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>
// CIR: cir.yield
-// CIR: } cleanup {{.*}} {
+// CIR: } cleanup all {
// CIR: cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token
// CIR: cir.yield
// CIR: }
@@ -698,7 +684,6 @@ void call_function_inside_try_catch_with_array_exception_type() {
// LLVM: %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]])
// LLVM: br label %[[CATCH_BODY:.*]]
// LLVM: [[CATCH_BODY]]:
-// LLVM: store ptr %[[TOKEN]], ptr {{.*}}, align 8
// LLVM: br label %[[END_CATCH:.*]]
// LLVM: [[END_CATCH]]:
// LLVM: call void @__cxa_end_catch()
@@ -764,17 +749,14 @@ void call_function_inside_try_catch_with_exception_type_and_catch_all() {
// CIR: cir.func {{.*}} @_Z64call_function_inside_try_catch_with_exception_type_and_catch_allv() personality(@__gxx_personality_v0)
// CIR: cir.scope {
-// CIR: %[[EXCEPTION_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["e"]
// CIR: cir.try {
// CIR: %[[CALL:.*]] = cir.call @_Z8divisionv()
// CIR: cir.yield
// CIR: } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] (%[[EH_TOKEN:.*]]: !cir.eh_token{{.*}}) {
// CIR: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[EH_TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>)
// CIR: cir.cleanup.scope {
-// CIR: %[[TMP:.*]] = cir.load {{.*}} %[[EXN_PTR]] : !cir.ptr<!s32i>, !s32i
-// CIR: cir.store {{.*}} %[[TMP]], %[[EXCEPTION_ADDR]] : !s32i, !cir.ptr<!s32i>
// CIR: cir.yield
-// CIR: } cleanup {{.*}} {
+// CIR: } cleanup all {
// CIR: cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token
// CIR: cir.yield
// CIR: }
@@ -783,7 +765,7 @@ void call_function_inside_try_catch_with_exception_type_and_catch_all() {
// CIR: %[[CATCH_TOKEN2:.*]], %{{.*}} = cir.begin_catch %[[EH_TOKEN2]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>)
// CIR: cir.cleanup.scope {
// CIR: cir.yield
-// CIR: } cleanup {{.*}} {
+// CIR: } cleanup all {
// CIR: cir.end_catch %[[CATCH_TOKEN2]] : !cir.catch_token
// CIR: cir.yield
// CIR: }
@@ -822,8 +804,6 @@ void call_function_inside_try_catch_with_exception_type_and_catch_all() {
// LLVM: %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]])
// LLVM: br label %[[CATCH_BODY:.*]]
// LLVM: [[CATCH_BODY]]:
-// LLVM: %[[LOAD:.*]] = load i32, ptr %[[TOKEN]], align 4
-// LLVM: store i32 %[[LOAD]], ptr {{.*}}, align 4
// LLVM: br label %[[END_CATCH:.*]]
// LLVM: [[END_CATCH]]:
// LLVM: call void @__cxa_end_catch()
@@ -1009,16 +989,14 @@ void call_function_inside_try_catch_with_aggregate_exception_type() {
}
-// CIR: cir.func {{.*}} @_Z60call_function_inside_try_catch_with_aggregate_exception_typev(){{.*}} personality(@__gxx_personality_v0) {
+// CIR: cir.func {{.*}} @_Z60call_function_inside_try_catch_with_aggregate_exception_typev() personality(@__gxx_personality_v0)
// CIR: cir.scope {
-// CIR: %[[E_ADDR:.*]] = cir.alloca !rec_CustomError, !cir.ptr<!rec_CustomError>, ["e"]
// CIR: cir.try {
// CIR: %[[CALL:.*]] = cir.call @_Z8divisionv() : () -> (!s32i {llvm.noundef})
// CIR: cir.yield
// CIR: } catch [type #cir.global_view<@_ZTI11CustomError> : !cir.ptr<!u8i>] (%{{.*}}: !cir.eh_token {{.*}}) {
// CIR: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %{{.*}} : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!rec_CustomError>)
// CIR: cir.cleanup.scope {
-// CIR: cir.copy %[[EXN_PTR]] to %[[E_ADDR]] : !cir.ptr<!rec_CustomError>
// CIR: cir.yield
// CIR: } cleanup all {
// CIR: cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token
@@ -1061,7 +1039,6 @@ void call_function_inside_try_catch_with_aggregate_exception_type() {
// LLVM: %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]])
// LLVM: br label %[[CATCH_BODY:.*]]
// LLVM: [[CATCH_BODY]]:
-// LLVM: call void @llvm.memcpy.p0.p0.i64(ptr %{{.*}}, ptr %[[TOKEN]], i64 4, i1 false)
// LLVM: br label %[[END_CATCH:.*]]
// LLVM: [[END_CATCH]]:
// LLVM: call void @__cxa_end_catch()
@@ -1130,17 +1107,12 @@ void call_function_inside_try_catch_with_ref_ptr_of_record_exception_type() {
}
// CIR: cir.func {{.*}} @_Z68call_function_inside_try_catch_with_ref_ptr_of_record_exception_typev(){{.*}} personality(@__gxx_personality_v0) {
-// CIR: %[[E_ADDR:.*]] = cir.alloca !cir.ptr<!cir.ptr<!rec_Record>>, !cir.ptr<!cir.ptr<!cir.ptr<!rec_Record>>>, ["ref_ptr", const]
-// CIR: %[[EXN_BYREF_TMP:.*]] = cir.alloca !cir.ptr<!rec_Record>, !cir.ptr<!cir.ptr<!rec_Record>>, ["exn.byref.tmp"]
// CIR: cir.try {
// CIR: %[[CALL:.*]] = cir.call @_Z8divisionv() : () -> (!s32i {llvm.noundef})
// CIR: cir.yield
// CIR: } catch [type #cir.global_view<@_ZTIP6Record> : !cir.ptr<!u8i>] (%[[EH_TOKEN:.*]]: !cir.eh_token {{.*}}) {
-// CIR: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[EH_TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!cir.ptr<!rec_Record>>)
+// CIR: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[EH_TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!cir.ptr<!cir.ptr<!rec_Record>>>)
// CIR: cir.cleanup.scope {
-// CIR: %[[EXN_PTR_REC_PTR:.*]] = cir.cast bitcast %[[EXN_PTR]] : !cir.ptr<!cir.ptr<!rec_Record>> -> !cir.ptr<!rec_Record>
-// CIR: cir.store {{.*}} %[[EXN_PTR_REC_PTR]], %[[EXN_BYREF_TMP]] : !cir.ptr<!rec_Record>, !cir.ptr<!cir.ptr<!rec_Record>>
-// CIR: cir.store {{.*}} %[[EXN_BYREF_TMP]], %[[E_ADDR]] : !cir.ptr<!cir.ptr<!rec_Record>>, !cir.ptr<!cir.ptr<!cir.ptr<!rec_Record>>>
// CIR: cir.yield
// CIR: } cleanup all {
// CIR: cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token
@@ -1153,8 +1125,6 @@ void call_function_inside_try_catch_with_ref_ptr_of_record_exception_type() {
// CIR: }
// LLVM: define {{.*}} void @_Z68call_function_inside_try_catch_with_ref_ptr_of_record_exception_typev() {{.*}} personality ptr @__gxx_personality_v0
-// LLVM: %[[E_ADDR:.*]] = alloca ptr
-// LLVM: %[[EXN_BYREF_TMP:.*]] = alloca ptr
// LLVM: br label %[[TRY_SCOPE:.*]]
// LLVM: [[TRY_SCOPE]]:
// LLVM: br label %[[TRY_BEGIN:.*]]
@@ -1185,8 +1155,6 @@ void call_function_inside_try_catch_with_ref_ptr_of_record_exception_type() {
// LLVM: %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]])
// LLVM: br label %[[CATCH_BODY:.*]]
// LLVM: [[CATCH_BODY]]:
-// LLVM: store ptr %[[TOKEN]], ptr %[[EXN_BYREF_TMP]], align 8
-// LLVM: store ptr %[[EXN_BYREF_TMP]], ptr %[[E_ADDR]], align 8
// LLVM: br label %[[END_CATCH:.*]]
// LLVM: [[END_CATCH]]:
// LLVM: call void @__cxa_end_catch()
@@ -1253,15 +1221,12 @@ void call_function_inside_try_catch_with_exception_member_ptr_type() {
// CIR: cir.func {{.*}} @_Z61call_function_inside_try_catch_with_exception_member_ptr_typev(){{.*}} personality(@__gxx_personality_v0) {
// CIR: cir.scope {
-// CIR: %[[E_ADDR:.*]] = cir.alloca !s64i, !cir.ptr<!s64i>, ["memberPtr"]
// CIR: cir.try {
// CIR: %[[CALL:.*]] = cir.call @_Z8divisionv() : () -> (!s32i {llvm.noundef})
// CIR: cir.yield
// CIR: } catch [type #cir.global_view<@_ZTIM6Recordi> : !cir.ptr<!u8i>] (%{{.*}}: !cir.eh_token {{.*}} {
// CIR: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %{{.*}} : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s64i>)
// CIR: cir.cleanup.scope {
-// CIR: %[[TMP:.*]] = cir.load {{.*}} %[[EXN_PTR]] : !cir.ptr<!s64i>, !s64i
-// CIR: cir.store {{.*}} %[[TMP]], %[[E_ADDR]] : !s64i, !cir.ptr<!s64i>
// CIR: cir.yield
// CIR: } cleanup all {
// CIR: cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token
@@ -1293,8 +1258,8 @@ void call_function_inside_try_catch_with_exception_member_ptr_type() {
// LLVM: %[[EH_SELECTOR_PHI:.*]] = phi i32 [ %[[EH_SELECTOR_VAL:.*]], %[[LANDING_PAD:.*]] ]
// LLVM: br label %[[DISPATCH:.*]]
// LLVM: [[DISPATCH]]:
-// LLVM: %[[EXN_OBJ_PHI1:.*]] = phi ptr [ %[[EXN_OBJ_PHI:.*]], %[[CATCH:.*]] ]
-// LLVM: %[[EH_SELECTOR_PHI1:.*]] = phi i32 [ %[[EH_SELECTOR_PHI:.*]], %[[CATCH:.*]] ]
+// LLVM: %[[EXN_OBJ_PHI1:.*]] = phi ptr [ %[[EXN_OBJ_PHI:.*]], %[[CATCH]] ]
+// LLVM: %[[EH_SELECTOR_PHI1:.*]] = phi i32 [ %[[EH_SELECTOR_PHI:.*]], %[[CATCH]] ]
// LLVM: %[[EH_TYPE_ID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIM6Recordi)
// LLVM: %[[TYPE_ID_EQ:.*]] = icmp eq i32 %[[EH_SELECTOR_PHI1]], %[[EH_TYPE_ID]]
// LLVM: br i1 %[[TYPE_ID_EQ]], label %[[BEGIN_CATCH:.*]], label %[[RESUME:.*]]
@@ -1304,8 +1269,6 @@ void call_function_inside_try_catch_with_exception_member_ptr_type() {
// LLVM: %[[TOKEN:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]])
// LLVM: br label %[[CATCH_BODY:.*]]
// LLVM: [[CATCH_BODY]]:
-// LLVM: %[[LOAD:.*]] = load i64, ptr %[[TOKEN]], align 8
-// LLVM: store i64 %[[LOAD]], ptr {{.*}}, align 8
// LLVM: br label %[[END_CATCH:.*]]
// LLVM: [[END_CATCH]]:
// LLVM: call void @__cxa_end_catch()
@@ -1362,3 +1325,276 @@ void call_function_inside_try_catch_with_exception_member_ptr_type() {
// OGCG: %[[EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } %[[TMP_EXCEPTION_INFO]], i32 %[[TMP_EH_TYPE_ID]], 1
// OGCG: resume { ptr, i32 } %[[EXCEPTION_INFO]]
+int init_catch_param_with_type_int() {
+ int rv = 0;
+ try {
+ division();
+ } catch (int x) {
+ rv = x;
+ }
+ return rv;
+}
+
+// CIR: cir.func {{.*}} @_Z30init_catch_param_with_type_intv() {{.*}} personality(@__gxx_personality_v0)
+// CIR: %[[RET_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]
+// CIR: %[[RV_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["rv", init]
+// CIR: cir.scope {
+// CIR: cir.try {
+// CIR: %[[CALL:.*]] = cir.call @_Z8divisionv() : () -> (!s32i {llvm.noundef})
+// CIR: cir.yield
+// CIR: } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] (%{{.*}}: !cir.eh_token {{.*}}) {
+// CIR: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %{{.*}} : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!s32i>)
+// CIR: cir.cleanup.scope {
+// CIR: %[[TMP_EXN:.*]] = cir.load {{.*}} %[[EXN_PTR]] : !cir.ptr<!s32i>, !s32i
+// CIR: cir.store {{.*}} %[[TMP_EXN]], %[[RV_ADDR]] : !s32i, !cir.ptr<!s32i>
+// CIR: cir.yield
+// CIR: } cleanup all {
+// CIR: cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token
+// CIR: cir.yield
+// CIR: }
+// CIR: cir.yield
+// CIR: } unwind (%{{.*}}: !cir.eh_token {{.*}}) {
+// CIR: cir.resume %{{.*}} : !cir.eh_token
+// CIR: }
+// CIR: }
+// CIR: %[[TMP_RV:.*]] = cir.load {{.*}} %[[RV_ADDR]] : !cir.ptr<!s32i>, !s32i
+// CIR: cir.store %[[TMP_RV]], %[[RET_ADDR]] : !s32i, !cir.ptr<!s32i>
+// CIR: %[[TMP_RET:.*]] = cir.load %[[RET_ADDR]] : !cir.ptr<!s32i>, !s32i
+// CIR: cir.return %[[TMP_RET]] : !s32i
+
+// LLVM: define {{.*}} i32 @_Z30init_catch_param_with_type_intv() {{.*}} personality ptr @__gxx_personality_v0
+// LLVM: %[[RET_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM: %[[RV_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM: br label %[[TRY_SCOPE:.*]]
+// LLVM: [[TRY_SCOPE]]:
+// LLVM: br label %[[TRY_BEGIN:.*]]
+// LLVM: [[TRY_BEGIN]]:
+// LLVM: %[[CALL:.*]] = invoke noundef i32 @_Z8divisionv()
+// LLVM: to label %[[INVOKE_CONT:.*]] unwind label %[[LANDING_PAD:.*]]
+// LLVM: [[INVOKE_CONT]]:
+// LLVM: br label %[[TRY_CONT:.*]]
+// LLVM: [[LANDING_PAD]]:
+// LLVM: %[[LP:.*]] = landingpad { ptr, i32 }
+// LLVM: catch ptr @_ZTIi
+// LLVM: %[[EXN_OBJ:.*]] = extractvalue { ptr, i32 } %[[LP]], 0
+// LLVM: %[[EH_SELECTOR_VAL:.*]] = extractvalue { ptr, i32 } %[[LP]], 1
+// LLVM: br label %[[CATCH:.*]]
+// LLVM: [[CATCH]]:
+// LLVM: %[[EXN_OBJ_PHI:.*]] = phi ptr [ %[[EXN_OBJ:.*]], %[[LANDING_PAD:.*]] ]
+// LLVM: %[[EH_SELECTOR_PHI:.*]] = phi i32 [ %[[EH_SELECTOR_VAL:.*]], %[[LANDING_PAD:.*]] ]
+// LLVM: br label %[[DISPATCH:.*]]
+// LLVM: [[DISPATCH]]:
+// LLVM: %[[EXN_OBJ_PHI1:.*]] = phi ptr [ %[[EXN_OBJ_PHI:.*]], %[[CATCH:.*]] ]
+// LLVM: %[[EH_SELECTOR_PHI1:.*]] = phi i32 [ %[[EH_SELECTOR_PHI:.*]], %[[CATCH]] ]
+// LLVM: %[[EH_TYPE_ID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi)
+// LLVM: %[[TYPE_ID_EQ:.*]] = icmp eq i32 %[[EH_SELECTOR_PHI1]], %[[EH_TYPE_ID]]
+// LLVM: br i1 %[[TYPE_ID_EQ]], label %[[BEGIN_CATCH:.*]], label %[[RESUME:.*]]
+// LLVM: [[BEGIN_CATCH]]:
+// LLVM: %[[EXN_OBJ_PHI2:.*]] = phi ptr [ %[[EXN_OBJ_PHI1:.*]], %[[DISPATCH:.*]] ]
+// LLVM: %[[EH_SELECTOR_PHI2:.*]] = phi i32 [ %[[EH_SELECTOR_PHI1:.*]], %[[DISPATCH:.*]] ]
+// LLVM: %[[EXN_PTR:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]])
+// LLVM: br label %[[CATCH_BODY:.*]]
+// LLVM: [[CATCH_BODY]]:
+// LLVM: %[[TMP_EXN:.*]] = load i32, ptr %[[EXN_PTR]], align 8
+// LLVM: store i32 %[[TMP_EXN]], ptr %[[RV_ADDR]], align 4
+// LLVM: br label %[[END_CATCH:.*]]
+// LLVM: [[END_CATCH]]:
+// LLVM: call void @__cxa_end_catch()
+// LLVM: br label %[[END_DISPATCH:.*]]
+// LLVM: [[END_DISPATCH]]:
+// LLVM: br label %[[END_TRY:.*]]
+// LLVM: [[END_TRY]]:
+// LLVM: br label %[[TRY_CONT:.*]]
+// LLVM: [[RESUME]]:
+// LLVM: %[[EXN_OBJ_PHI3:.*]] = phi ptr [ %[[EXN_OBJ_PHI1:.*]], %[[DISPATCH:.*]] ]
+// LLVM: %[[EH_SELECTOR_PHI3:.*]] = phi i32 [ %[[EH_SELECTOR_PHI1:.*]], %[[DISPATCH:.*]] ]
+// LLVM: %[[TMP_EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } poison, ptr %[[EXN_OBJ_PHI3]], 0
+// LLVM: %[[EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } %[[TMP_EXCEPTION_INFO]], i32 %[[EH_SELECTOR_PHI3]], 1
+// LLVM: resume { ptr, i32 } %[[EXCEPTION_INFO]]
+// LLVM: [[TRY_CONT]]:
+// LLVM: br label %[[DONE:.*]]
+// LLVM: [[DONE]]:
+// LLVM: %[[TMP_RV:.*]] = load i32, ptr %[[RV_ADDR]], align 4
+// LLVM: store i32 %[[TMP_RV]], ptr %[[RET_ADDR]], align 4
+// LLVM: %[[TMP_RET:.*]] = load i32, ptr %[[RET_ADDR]], align 4
+// LLVM: ret i32 %[[TMP_RET]]
+
+// OGCG: define {{.*}} i32 @_Z30init_catch_param_with_type_intv() {{.*}} personality ptr @__gxx_personality_v0
+// OGCG: %[[RV_ADDR:.*]] = alloca i32, align 4
+// OGCG: %[[EXCEPTION_ADDR:.*]] = alloca ptr, align 8
+// OGCG: %[[EH_TYPE_ID_ADDR:.*]] = alloca i32, align 4
+// OGCG: %[[X_ADDR:.*]] = alloca i32, align 4
+// OGCG: %[[CALL:.*]] = invoke noundef i32 @_Z8divisionv()
+// OGCG: to label %[[INVOKE_NORMAL:.*]] unwind label %[[INVOKE_UNWIND:.*]]
+// OGCG: [[INVOKE_NORMAL]]:
+// OGCG: br label %[[TRY_CONT:.*]]
+// OGCG: [[INVOKE_UNWIND]]:
+// OGCG: %[[LANDING_PAD:.*]] = landingpad { ptr, i32 }
+// OGCG: catch ptr @_ZTIi
+// OGCG: %[[EXCEPTION:.*]] = extractvalue { ptr, i32 } %[[LANDING_PAD]], 0
+// OGCG: store ptr %[[EXCEPTION]], ptr %[[EXCEPTION_ADDR]], align 8
+// OGCG: %[[EH_TYPE_ID:.*]] = extractvalue { ptr, i32 } %[[LANDING_PAD]], 1
+// OGCG: store i32 %[[EH_TYPE_ID]], ptr %[[EH_TYPE_ID_ADDR]], align 4
+// OGCG: br label %[[CATCH_DISPATCH]]
+// OGCG: [[CATCH_DISPATCH]]:
+// OGCG: %[[TMP_EH_TYPE_ID:.*]] = load i32, ptr %[[EH_TYPE_ID_ADDR]], align 4
+// OGCG: %[[EH_TYPE_ID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIi)
+// OGCG: %[[TYPE_ID_EQ:.*]] = icmp eq i32 %[[TMP_EH_TYPE_ID]], %[[EH_TYPE_ID]]
+// OGCG: br i1 %[[TYPE_ID_EQ]], label %[[CATCH_EXCEPTION:.*]], label %[[EH_RESUME:.*]]
+// OGCG: [[CATCH_EXCEPTION]]:
+// OGCG: %[[TMP_EXCEPTION:.*]] = load ptr, ptr %[[EXCEPTION_ADDR]], align 8
+// OGCG: %[[BEGIN_CATCH:.*]] = call ptr @__cxa_begin_catch(ptr %[[TMP_EXCEPTION]])
+// OGCG: %[[TMP_BEGIN_CATCH:.*]] = load i32, ptr %[[BEGIN_CATCH]], align 4
+// OGCG: store i32 %[[TMP_BEGIN_CATCH]], ptr %[[X_ADDR]], align 4
+// OGCG: %[[TMP_X:.*]] = load i32, ptr %[[X_ADDR]], align 4
+// OGCG: store i32 %[[TMP_X]], ptr %[[RV_ADDR]], align 4
+// OGCG: call void @__cxa_end_catch()
+// OGCG: br label %[[TRY_CONT]]
+// OGCG: [[TRY_CONT]]:
+// OGCG: %[[TMP_RV:.*]] = load i32, ptr %[[RV_ADDR]], align 4
+// OGCG: ret i32 %[[TMP_RV]]
+// OGCG: [[EH_RESUME]]:
+// OGCG: %[[TMP_EXCEPTION:.*]] = load ptr, ptr %[[EXCEPTION_ADDR]], align 8
+// OGCG: %[[TMP_EH_TYPE_ID:.*]] = load i32, ptr %[[EH_TYPE_ID_ADDR]], align 4
+// OGCG: %[[TMP_EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } poison, ptr %[[TMP_EXCEPTION]], 0
+// OGCG: %[[EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } %[[TMP_EXCEPTION_INFO]], i32 %[[TMP_EH_TYPE_ID]], 1
+// OGCG: resume { ptr, i32 } %[[EXCEPTION_INFO]]
+
+
+int init_catch_param_with_type_int_ptr() {
+ int rv = 0;
+ try {
+ division();
+ } catch (int *x) {
+ rv = *x;
+ }
+ return rv;
+}
+
+// CIR: cir.func {{.*}} @_Z34init_catch_param_with_type_int_ptrv() {{.*}} personality(@__gxx_personality_v0)
+// CIR: %[[RET_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["__retval"]
+// CIR: %[[RV_ADDR:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["rv", init]
+// CIR: cir.scope {
+// CIR: cir.try {
+// CIR: %[[CALL:.*]] = cir.call @_Z8divisionv() : () -> (!s32i {llvm.noundef})
+// CIR: cir.yield
+// CIR: } catch [type #cir.global_view<@_ZTIPi> : !cir.ptr<!u8i>] (%{{.*}}: !cir.eh_token {{.*}}) {
+// CIR: %catch_token, %exn_ptr = cir.begin_catch %{{.*}} : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!cir.ptr<!s32i>>)
+// CIR: cir.cleanup.scope {
+// CIR: %[[DEREF_EXN_PTR:.*]] = cir.load deref {{.*}} %[[EXN_PTR]] : !cir.ptr<!cir.ptr<!s32i>>, !cir.ptr<!s32i>
+// CIR: %[[EXN_PTR:.*]] = cir.load {{.*}} %[[DEREF_EXN_PTR]] : !cir.ptr<!s32i>, !s32i
+// CIR: cir.store {{.*}} %[[EXN_PTR]], %[[RV_ADDR]] : !s32i, !cir.ptr<!s32i>
+// CIR: cir.yield
+// CIR: } cleanup all {
+// CIR: cir.end_catch %catch_token : !cir.catch_token
+// CIR: cir.yield
+// CIR: }
+// CIR: cir.yield
+// CIR: } unwind (%{{.*}}: !cir.eh_token {{.*}} {
+// CIR: cir.resume %{{.*}} : !cir.eh_token
+// CIR: }
+// CIR: }
+// CIR: %[[TMP_RV:.*]] = cir.load {{.*}} %[[RV_ADDR]] : !cir.ptr<!s32i>, !s32i
+// CIR: cir.store %[[TMP_RV]], %[[RET_ADDR]] : !s32i, !cir.ptr<!s32i>
+// CIR: %[[TMP_RET:.*]] = cir.load %[[RET_ADDR]] : !cir.ptr<!s32i>, !s32i
+// CIR: cir.return %[[TMP_RET]] : !s32i
+
+// LLVM: define {{.*}} i32 @_Z34init_catch_param_with_type_int_ptrv() {{.*}} personality ptr @__gxx_personality_v0
+// LLVM: %[[RET_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM: %[[RV_ADDR:.*]] = alloca i32, i64 1, align 4
+// LLVM: br label %[[TRY_SCOPE:.*]]
+// LLVM: [[TRY_SCOPE]]:
+// LLVM: br label %[[TRY_BEGIN:.*]]
+// LLVM: [[TRY_BEGIN]]:
+// LLVM: %[[CALL:.*]] = invoke noundef i32 @_Z8divisionv()
+// LLVM: to label %[[INVOKE_CONT:.*]] unwind label %[[LANDING_PAD:.*]]
+// LLVM: [[INVOKE_CONT]]:
+// LLVM: br label %[[TRY_CONT:.*]]
+// LLVM: [[LANDING_PAD]]:
+// LLVM: %[[LP:.*]] = landingpad { ptr, i32 }
+// LLVM: catch ptr @_ZTIPi
+// LLVM: %[[EXN_OBJ:.*]] = extractvalue { ptr, i32 } %[[LP]], 0
+// LLVM: %[[EH_SELECTOR_VAL:.*]] = extractvalue { ptr, i32 } %[[LP]], 1
+// LLVM: br label %[[CATCH:.*]]
+// LLVM: [[CATCH]]:
+// LLVM: %[[EXN_OBJ_PHI:.*]] = phi ptr [ %[[EXN_OBJ:.*]], %[[LANDING_PAD:.*]] ]
+// LLVM: %[[EH_SELECTOR_PHI:.*]] = phi i32 [ %[[EH_SELECTOR_VAL:.*]], %[[LANDING_PAD:.*]] ]
+// LLVM: br label %[[DISPATCH:.*]]
+// LLVM: [[DISPATCH]]:
+// LLVM: %[[EXN_OBJ_PHI1:.*]] = phi ptr [ %[[EXN_OBJ_PHI:.*]], %[[CATCH:.*]] ]
+// LLVM: %[[EH_SELECTOR_PHI1:.*]] = phi i32 [ %[[EH_SELECTOR_PHI:.*]], %[[CATCH]] ]
+// LLVM: %[[EH_TYPE_ID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIPi)
+// LLVM: %[[TYPE_ID_EQ:.*]] = icmp eq i32 %[[EH_SELECTOR_PHI1]], %[[EH_TYPE_ID]]
+// LLVM: br i1 %[[TYPE_ID_EQ]], label %[[BEGIN_CATCH:.*]], label %[[RESUME:.*]]
+// LLVM: [[BEGIN_CATCH]]:
+// LLVM: %[[EXN_OBJ_PHI2:.*]] = phi ptr [ %[[EXN_OBJ_PHI1:.*]], %[[DISPATCH:.*]] ]
+// LLVM: %[[EH_SELECTOR_PHI2:.*]] = phi i32 [ %[[EH_SELECTOR_PHI1:.*]], %[[DISPATCH:.*]] ]
+// LLVM: %[[EXN_PTR:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXN_OBJ_PHI2]])
+// LLVM: br label %[[CATCH_BODY:.*]]
+// LLVM: [[CATCH_BODY]]:
+// LLVM: %[[DEREF_EXN_PTR:.*]] = load ptr, ptr %[[EXN_PTR]], align 8
+// LLVM: %[[TMP_EXN:.*]] = load i32, ptr %[[DEREF_EXN_PTR]], align 4
+// LLVM: store i32 %[[TMP_EXN]], ptr %[[RV_ADDR]], align 4
+// LLVM: br label %[[END_CATCH:.*]]
+// LLVM: [[END_CATCH]]:
+// LLVM: call void @__cxa_end_catch()
+// LLVM: br label %[[END_DISPATCH:.*]]
+// LLVM: [[END_DISPATCH]]:
+// LLVM: br label %[[END_TRY:.*]]
+// LLVM: [[END_TRY]]:
+// LLVM: br label %[[TRY_CONT:.*]]
+// LLVM: [[RESUME]]:
+// LLVM: %[[EXN_OBJ_PHI3:.*]] = phi ptr [ %[[EXN_OBJ_PHI1:.*]], %[[DISPATCH:.*]] ]
+// LLVM: %[[EH_SELECTOR_PHI3:.*]] = phi i32 [ %[[EH_SELECTOR_PHI1:.*]], %[[DISPATCH:.*]] ]
+// LLVM: %[[TMP_EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } poison, ptr %[[EXN_OBJ_PHI3]], 0
+// LLVM: %[[EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } %[[TMP_EXCEPTION_INFO]], i32 %[[EH_SELECTOR_PHI3]], 1
+// LLVM: resume { ptr, i32 } %[[EXCEPTION_INFO]]
+// LLVM: [[TRY_CONT]]:
+// LLVM: br label %[[DONE:.*]]
+// LLVM: [[DONE]]:
+// LLVM: %[[TMP_RV:.*]] = load i32, ptr %[[RV_ADDR]], align 4
+// LLVM: store i32 %[[TMP_RV]], ptr %[[RET_ADDR]], align 4
+// LLVM: %[[TMP_RET:.*]] = load i32, ptr %[[RET_ADDR]], align 4
+// LLVM: ret i32 %[[TMP_RET]]
+
+
+// OGCG: define {{.*}} i32 @_Z34init_catch_param_with_type_int_ptrv() {{.*}} personality ptr @__gxx_personality_v0
+// OGCG: %[[RV_ADDR:.*]] = alloca i32, align 4
+// OGCG: %[[EXCEPTION_ADDR:.*]] = alloca ptr, align 8
+// OGCG: %[[EH_TYPE_ID_ADDR:.*]] = alloca i32, align 4
+// OGCG: %[[C_ADDR:.*]] = alloca ptr, align 8
+// OGCG: %[[CALL:.*]] = invoke noundef i32 @_Z8divisionv()
+// OGCG: to label %[[INVOKE_NORMAL:.*]] unwind label %[[INVOKE_UNWIND:.*]]
+// OGCG: [[INVOKE_NORMAL]]:
+// OGCG: br label %[[TRY_CONT:.*]]
+// OGCG: [[INVOKE_UNWIND]]:
+// OGCG: %[[LANDING_PAD:.*]] = landingpad { ptr, i32 }
+// OGCG: catch ptr @_ZTIPi
+// OGCG: %[[EXCEPTION:.*]] = extractvalue { ptr, i32 } %[[LANDING_PAD]], 0
+// OGCG: store ptr %[[EXCEPTION]], ptr %[[EXCEPTION_ADDR]], align 8
+// OGCG: %[[EH_TYPE_ID:.*]] = extractvalue { ptr, i32 } %[[LANDING_PAD]], 1
+// OGCG: store i32 %[[EH_TYPE_ID]], ptr %[[EH_TYPE_ID_ADDR]], align 4
+// OGCG: br label %[[CATCH_DISPATCH]]
+// OGCG: [[CATCH_DISPATCH]]:
+// OGCG: %[[TMP_EH_TYPE_ID:.*]] = load i32, ptr %[[EH_TYPE_ID_ADDR]], align 4
+// OGCG: %[[EH_TYPE_ID:.*]] = call i32 @llvm.eh.typeid.for.p0(ptr @_ZTIPi)
+// OGCG: %[[TYPE_ID_EQ:.*]] = icmp eq i32 %[[TMP_EH_TYPE_ID]], %[[EH_TYPE_ID]]
+// OGCG: br i1 %[[TYPE_ID_EQ]], label %[[CATCH_EXCEPTION:.*]], label %[[EH_RESUME:.*]]
+// OGCG: [[CATCH_EXCEPTION]]:
+// OGCG: %[[TMP_EXCEPTION:.*]] = load ptr, ptr %[[EXCEPTION_ADDR]], align 8
+// OGCG: %[[BEGIN_CATCH:.*]] = call ptr @__cxa_begin_catch(ptr %[[TMP_EXCEPTION]])
+// OGCG: store ptr %[[BEGIN_CATCH]], ptr %[[X_ADDR]], align 8
+// OGCG: %[[DEREF_X:.*]] = load ptr, ptr %[[X_ADDR]], align 8
+// OGCG: %[[TMP_X:.*]] = load i32, ptr %[[DEREF_X]], align 4
+// OGCG: store i32 %[[TMP_X]], ptr %[[RV_ADDR]], align 4
+// OGCG: call void @__cxa_end_catch()
+// OGCG: br label %[[TRY_CONT]]
+// OGCG: [[TRY_CONT]]:
+// OGCG: %[[TMP_RV:.*]] = load i32, ptr %[[RV_ADDR]], align 4
+// OGCG: ret i32 %[[TMP_RV]]
+// OGCG: [[EH_RESUME]]:
+// OGCG: %[[TMP_EXCEPTION:.*]] = load ptr, ptr %[[EXCEPTION_ADDR]], align 8
+// OGCG: %[[TMP_EH_TYPE_ID:.*]] = load i32, ptr %[[EH_TYPE_ID_ADDR]], align 4
+// OGCG: %[[TMP_EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } poison, ptr %[[TMP_EXCEPTION]], 0
+// OGCG: %[[EXCEPTION_INFO:.*]] = insertvalue { ptr, i32 } %[[TMP_EXCEPTION_INFO]], i32 %[[TMP_EH_TYPE_ID]], 1
+// OGCG: resume { ptr, i32 } %[[EXCEPTION_INFO]]
More information about the cfe-commits
mailing list