Skip to content

Commit 111e875

Browse files
committed
[CIR] Upstream Exception EhInflight op
1 parent 032900e commit 111e875

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
@@ -4490,6 +4490,35 @@ def CIR_TryOp : CIR_Op<"try",[
44904490
let hasLLVMLowering = false;
44914491
}
44924492

4493+
//===----------------------------------------------------------------------===//
4494+
// Exception related: EhInflightOp
4495+
//===----------------------------------------------------------------------===//
4496+
4497+
def CIR_EhInflightOp : CIR_Op<"eh.inflight_exception"> {
4498+
let summary = "Materialize the catch clause formal parameter";
4499+
let description = [{
4500+
`cir.eh.inflight_exception` returns two values:
4501+
- `exception_ptr`: The exception pointer for the inflight exception
4502+
- `type_id`: pointer to the exception object
4503+
This operation is expected to be the first one basic blocks on the
4504+
exception path out of `cir.try_call` operations.
4505+
4506+
The `cleanup` attribute indicates that clean up code might run before the
4507+
values produced by this operation are used to gather exception information.
4508+
This helps CIR to pass down more accurate information for LLVM lowering
4509+
to landingpads.
4510+
}];
4511+
4512+
let arguments = (ins UnitAttr:$cleanup,
4513+
OptionalAttr<FlatSymbolRefArrayAttr>:$sym_type_list);
4514+
let results = (outs CIR_VoidPtrType:$exception_ptr, CIR_UInt32:$type_id);
4515+
let assemblyFormat = [{
4516+
(`cleanup` $cleanup^)?
4517+
($sym_type_list^)?
4518+
attr-dict
4519+
}];
4520+
}
4521+
44934522
//===----------------------------------------------------------------------===//
44944523
// Atomic operations
44954524
//===----------------------------------------------------------------------===//

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

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3002,6 +3002,88 @@ mlir::LogicalResult CIRToLLVMAllocExceptionOpLowering::matchAndRewrite(
30023002
return mlir::success();
30033003
}
30043004

3005+
static mlir::LLVM::LLVMStructType
3006+
getLLVMLandingPadStructTy(mlir::ConversionPatternRewriter &rewriter) {
3007+
// Create the landing pad type: struct { ptr, i32 }
3008+
mlir::MLIRContext *ctx = rewriter.getContext();
3009+
auto llvmPtr = mlir::LLVM::LLVMPointerType::get(ctx);
3010+
llvm::SmallVector<mlir::Type> structFields = {llvmPtr, rewriter.getI32Type()};
3011+
return mlir::LLVM::LLVMStructType::getLiteral(ctx, structFields);
3012+
}
3013+
3014+
mlir::LogicalResult CIRToLLVMEhInflightOpLowering::matchAndRewrite(
3015+
cir::EhInflightOp op, OpAdaptor adaptor,
3016+
mlir::ConversionPatternRewriter &rewriter) const {
3017+
auto llvmFn = op->getParentOfType<mlir::LLVM::LLVMFuncOp>();
3018+
assert(llvmFn && "expected LLVM function parent");
3019+
mlir::Block *entryBlock = &llvmFn.getRegion().front();
3020+
assert(entryBlock->isEntryBlock());
3021+
3022+
mlir::ArrayAttr symListAttr = op.getSymTypeListAttr();
3023+
mlir::SmallVector<mlir::Value, 4> symAddrs;
3024+
3025+
auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3026+
mlir::Location loc = op.getLoc();
3027+
3028+
// %landingpad = landingpad { ptr, i32 }
3029+
// Note that since llvm.landingpad has to be the first operation on the
3030+
// block, any needed value for its operands has to be added somewhere else.
3031+
if (symListAttr) {
3032+
// catch ptr @_ZTIi
3033+
// catch ptr @_ZTIPKc
3034+
for (mlir::Attribute attr : symListAttr) {
3035+
auto symAttr = cast<mlir::FlatSymbolRefAttr>(attr);
3036+
// Generate `llvm.mlir.addressof` for each symbol, and place those
3037+
// operations in the LLVM function entry basic block.
3038+
mlir::OpBuilder::InsertionGuard guard(rewriter);
3039+
rewriter.setInsertionPointToStart(entryBlock);
3040+
mlir::Value addrOp = mlir::LLVM::AddressOfOp::create(
3041+
rewriter, loc, llvmPtrTy, symAttr.getValue());
3042+
symAddrs.push_back(addrOp);
3043+
}
3044+
} else if (!op.getCleanup()) {
3045+
// catch ptr null
3046+
mlir::OpBuilder::InsertionGuard guard(rewriter);
3047+
rewriter.setInsertionPointToStart(entryBlock);
3048+
mlir::Value nullOp = mlir::LLVM::ZeroOp::create(rewriter, loc, llvmPtrTy);
3049+
symAddrs.push_back(nullOp);
3050+
}
3051+
3052+
// %slot = extractvalue { ptr, i32 } %x, 0
3053+
// %selector = extractvalue { ptr, i32 } %x, 1
3054+
mlir::LLVM::LLVMStructType llvmLandingPadStructTy =
3055+
getLLVMLandingPadStructTy(rewriter);
3056+
auto landingPadOp = mlir::LLVM::LandingpadOp::create(
3057+
rewriter, loc, llvmLandingPadStructTy, symAddrs);
3058+
3059+
if (op.getCleanup())
3060+
landingPadOp.setCleanup(true);
3061+
3062+
mlir::Value slot =
3063+
mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 0);
3064+
mlir::Value selector =
3065+
mlir::LLVM::ExtractValueOp::create(rewriter, loc, landingPadOp, 1);
3066+
rewriter.replaceOp(op, mlir::ValueRange{slot, selector});
3067+
3068+
// Landing pads are required to be in LLVM functions with personality
3069+
// attribute.
3070+
// TODO(cir): for now hardcode personality creation in order to start
3071+
// adding exception tests, once we annotate CIR with such information,
3072+
// change it to be in FuncOp lowering instead.
3073+
mlir::OpBuilder::InsertionGuard guard(rewriter);
3074+
// Insert personality decl before the current function.
3075+
rewriter.setInsertionPoint(llvmFn);
3076+
auto personalityFnTy =
3077+
mlir::LLVM::LLVMFunctionType::get(rewriter.getI32Type(), {},
3078+
/*isVarArg=*/true);
3079+
// Get or create `__gxx_personality_v0`
3080+
const StringRef fnName = "__gxx_personality_v0";
3081+
createLLVMFuncOpIfNotExist(rewriter, op, fnName, personalityFnTy);
3082+
llvmFn.setPersonality(fnName);
3083+
3084+
return mlir::success();
3085+
}
3086+
30053087
mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
30063088
cir::TrapOp op, OpAdaptor adaptor,
30073089
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)