Skip to content

Commit 5715179

Browse files
committed
[CIR] Upstream Exception EhInflight op
1 parent be9e287 commit 5715179

File tree

3 files changed

+126
-0
lines changed

3 files changed

+126
-0
lines changed

clang/include/clang/CIR/Dialect/IR/CIROps.td

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4606,6 +4606,35 @@ def CIR_TryOp : CIR_Op<"try",[
46064606
let hasLLVMLowering = false;
46074607
}
46084608

4609+
//===----------------------------------------------------------------------===//
4610+
// Exception related: EhInflightOp
4611+
//===----------------------------------------------------------------------===//
4612+
4613+
def CIR_EhInflightOp : CIR_Op<"eh.inflight_exception"> {
4614+
let summary = "Materialize the catch clause formal parameter";
4615+
let description = [{
4616+
`cir.eh.inflight_exception` returns two values:
4617+
- `exception_ptr`: The exception pointer for the inflight exception
4618+
- `type_id`: pointer to the exception object
4619+
This operation is expected to be the first one basic blocks on the
4620+
exception path out of `cir.try_call` operations.
4621+
4622+
The `cleanup` attribute indicates that clean up code might run before the
4623+
values produced by this operation are used to gather exception information.
4624+
This helps CIR to pass down more accurate information for LLVM lowering
4625+
to landingpads.
4626+
}];
4627+
4628+
let arguments = (ins UnitAttr:$cleanup,
4629+
OptionalAttr<FlatSymbolRefArrayAttr>:$sym_type_list);
4630+
let results = (outs CIR_VoidPtrType:$exception_ptr, CIR_UInt32:$type_id);
4631+
let assemblyFormat = [{
4632+
(`cleanup` $cleanup^)?
4633+
($sym_type_list^)?
4634+
attr-dict
4635+
}];
4636+
}
4637+
46094638
//===----------------------------------------------------------------------===//
46104639
// Atomic operations
46114640
//===----------------------------------------------------------------------===//

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3065,6 +3065,88 @@ mlir::LogicalResult CIRToLLVMAllocExceptionOpLowering::matchAndRewrite(
30653065
return mlir::success();
30663066
}
30673067

3068+
static mlir::LLVM::LLVMStructType
3069+
getLLVMLandingPadStructTy(mlir::ConversionPatternRewriter &rewriter) {
3070+
// Create the landing pad type: struct { ptr, i32 }
3071+
mlir::MLIRContext *ctx = rewriter.getContext();
3072+
auto llvmPtr = mlir::LLVM::LLVMPointerType::get(ctx);
3073+
llvm::SmallVector<mlir::Type> structFields = {llvmPtr, rewriter.getI32Type()};
3074+
return mlir::LLVM::LLVMStructType::getLiteral(ctx, structFields);
3075+
}
3076+
3077+
mlir::LogicalResult CIRToLLVMEhInflightOpLowering::matchAndRewrite(
3078+
cir::EhInflightOp op, OpAdaptor adaptor,
3079+
mlir::ConversionPatternRewriter &rewriter) const {
3080+
auto llvmFn = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
3081+
assert(llvmFn && "expected LLVM function parent");
3082+
mlir::Block *entryBlock = &llvmFn.getRegion().front();
3083+
assert(entryBlock->isEntryBlock());
3084+
3085+
mlir::ArrayAttr symListAttr = op.getSymTypeListAttr();
3086+
mlir::SmallVector<mlir::Value, 4> symAddrs;
3087+
3088+
auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3089+
mlir::Location loc = op.getLoc();
3090+
3091+
// %landingpad = landingpad { ptr, i32 }
3092+
// Note that since llvm.landingpad has to be the first operation on the
3093+
// block, any needed value for its operands has to be added somewhere else.
3094+
if (symListAttr) {
3095+
// catch ptr @_ZTIi
3096+
// catch ptr @_ZTIPKc
3097+
for (mlir::Attribute attr : symListAttr) {
3098+
auto symAttr = cast<mlir::FlatSymbolRefAttr>(attr);
3099+
// Generate `llvm.mlir.addressof` for each symbol, and place those
3100+
// operations in the LLVM function entry basic block.
3101+
mlir::OpBuilder::InsertionGuard guard(rewriter);
3102+
rewriter.setInsertionPointToStart(entryBlock);
3103+
mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
3104+
rewriter, loc, llvmPtrTy, symAttr.getValue());
3105+
symAddrs.push_back(addrOp);
3106+
}
3107+
} else if (!op.getCleanup()) {
3108+
// catch ptr null
3109+
mlir::OpBuilder::InsertionGuard guard(rewriter);
3110+
rewriter.setInsertionPointToStart(entryBlock);
3111+
mlir::Value nullOp = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3112+
symAddrs.push_back(nullOp);
3113+
}
3114+
3115+
// %slot = extractvalue { ptr, i32 } %x, 0
3116+
// %selector = extractvalue { ptr, i32 } %x, 1
3117+
mlir::LLVM::LLVMStructType llvmLandingPadStructTy =
3118+
getLLVMLandingPadStructTy(rewriter);
3119+
auto landingPadOp = mlir::LLVM::LandingpadOp::create(
3120+
rewriter, loc, llvmLandingPadStructTy, symAddrs);
3121+
3122+
if (op.getCleanup())
3123+
landingPadOp.setCleanup(true);
3124+
3125+
mlir::Value slot =
3126+
mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 0);
3127+
mlir::Value selector =
3128+
mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 1);
3129+
rewriter.replaceOp(op, mlir::ValueRange{slot, selector});
3130+
3131+
// Landing pads are required to be in LLVM functions with personality
3132+
// attribute.
3133+
// TODO(cir): for now hardcode personality creation in order to start
3134+
// adding exception tests, once we annotate CIR with such information,
3135+
// change it to be in FuncOp lowering instead.
3136+
mlir::OpBuilder::InsertionGuard guard(rewriter);
3137+
// Insert personality decl before the current function.
3138+
rewriter.setInsertionPoint(llvmFn);
3139+
auto personalityFnTy =
3140+
mlir::LLVM::LLVMFunctionType::get(rewriter.getI32Type(), {},
3141+
/*isVarArg=*/true);
3142+
// Get or create `__gxx_personality_v0`
3143+
const StringRef fnName = "__gxx_personality_v0";
3144+
createLLVMFuncOpIfNotExist(rewriter, op, fnName, personalityFnTy);
3145+
llvmFn.setPersonality(fnName);
3146+
3147+
return mlir::success();
3148+
}
3149+
30683150
mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
30693151
cir::TrapOp op, OpAdaptor adaptor,
30703152
mlir::ConversionPatternRewriter &rewriter) const {

clang/test/CIR/IR/eh-inflight.cir

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: cir-opt %s --verify-roundtrip | FileCheck %s
2+
3+
module {
4+
5+
cir.func dso_local @function_with_inflight_exception() {
6+
%exception_ptr, %type_id = cir.eh.inflight_exception
7+
cir.return
8+
}
9+
10+
// CHECK: cir.func dso_local @function_with_inflight_exception() {
11+
// CHECK: %exception_ptr, %type_id = cir.eh.inflight_exception
12+
// CHECK: cir.return
13+
// CHECK: }
14+
15+
}

0 commit comments

Comments
 (0)