https://github.com/Lancern updated https://github.com/llvm/llvm-project/pull/151363
>From 8f1deb8f71b2fec45c706ae4a6b21a87cab43bc9 Mon Sep 17 00:00:00 2001 From: Sirui Mu <msrlanc...@gmail.com> Date: Thu, 31 Jul 2025 01:08:22 +0800 Subject: [PATCH] [CIR] Add CIRGen for cir.unreachable and cir.trap --- clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 11 ++++ clang/lib/CIR/CodeGen/CIRGenExpr.cpp | 14 +++++ clang/lib/CIR/CodeGen/CIRGenFunction.h | 20 +++++++ .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 10 +++- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.h | 10 ++++ clang/test/CIR/CodeGen/builtin_call.cpp | 60 +++++++++++++++++++ 6 files changed, 124 insertions(+), 1 deletion(-) diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 9049a016b2b9b..fd652981cc51a 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -21,6 +21,7 @@ #include "mlir/Support/LLVM.h" #include "clang/AST/Expr.h" #include "clang/AST/GlobalDecl.h" +#include "clang/Basic/Builtins.h" #include "clang/CIR/MissingFeatures.h" #include "llvm/Support/ErrorHandling.h" @@ -269,6 +270,16 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID, case Builtin::BI__builtin_rotateright32: case Builtin::BI__builtin_rotateright64: return emitRotate(e, /*isRotateLeft=*/false); + + case Builtin::BI__builtin_trap: { + emitTrap(loc, /*createNewBlock=*/true); + return RValue::get(nullptr); + } + + case Builtin::BI__builtin_unreachable: { + emitUnreachable(e->getExprLoc(), /*createNewBlock=*/true); + return RValue::get(nullptr); + } } // If this is an alias for a lib function (e.g. __builtin_sin), emit diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp index c18498f80e99f..43e1a8efbd25a 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -1780,6 +1780,20 @@ LValue CIRGenFunction::emitLoadOfReferenceLValue(Address refAddr, pointeeBaseInfo); } +void CIRGenFunction::emitTrap(mlir::Location loc, bool createNewBlock) { + cir::TrapOp::create(builder, loc); + if (createNewBlock) + builder.createBlock(builder.getBlock()->getParent()); +} + +void CIRGenFunction::emitUnreachable(clang::SourceLocation loc, + bool createNewBlock) { + assert(!cir::MissingFeatures::sanitizers()); + cir::UnreachableOp::create(builder, getLoc(loc)); + if (createNewBlock) + builder.createBlock(builder.getBlock()->getParent()); +} + mlir::Value CIRGenFunction::createDummyValue(mlir::Location loc, clang::QualType qt) { mlir::Type t = convertType(qt); diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h b/clang/lib/CIR/CodeGen/CIRGenFunction.h index 603f75078c519..0c1cb26d4f84a 100644 --- a/clang/lib/CIR/CodeGen/CIRGenFunction.h +++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h @@ -1199,8 +1199,28 @@ class CIRGenFunction : public CIRGenTypeCache { /// to conserve the high level information. mlir::Value emitToMemory(mlir::Value value, clang::QualType ty); + /// Emit a trap instruction, which is used to abort the program in an abnormal + /// way, usually for debugging purposes. + /// \p createNewBlock indicates whether to create a new block for the IR + /// builder. Since the `cir.trap` operation is a terminator, operations that + /// follow a trap cannot be emitted after `cir.trap` in the same block. To + /// ensure these operations get emitted successfully, you need to create a new + /// dummy block and set the insertion point there before continuing from the + /// trap operation. + void emitTrap(mlir::Location loc, bool createNewBlock); + LValue emitUnaryOpLValue(const clang::UnaryOperator *e); + /// Emit a reached-unreachable diagnostic if \p loc is valid and runtime + /// checking is enabled. Otherwise, just emit an unreachable instruction. + /// \p createNewBlock indicates whether to create a new block for the IR + /// builder. Since the `cir.unreachable` operation is a terminator, operations + /// that follow an unreachable point cannot be emitted after `cir.unreachable` + /// in the same block. To ensure these operations get emitted successfully, + /// you need to create a dummy block and set the insertion point there before + /// continuing from the unreachable point. + void emitUnreachable(clang::SourceLocation loc, bool createNewBlock); + /// This method handles emission of any variable declaration /// inside a function, including static vars etc. void emitVarDecl(const clang::VarDecl &d); diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 957a51ab334aa..ce245681e4443 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -2214,7 +2214,8 @@ void ConvertCIRToLLVMPass::runOnOperation() { CIRToLLVMVecShuffleDynamicOpLowering, CIRToLLVMVecShuffleOpLowering, CIRToLLVMVecSplatOpLowering, - CIRToLLVMVecTernaryOpLowering + CIRToLLVMVecTernaryOpLowering, + CIRToLLVMUnreachableOpLowering // clang-format on >(converter, patterns.getContext()); @@ -2270,6 +2271,13 @@ mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite( } } +mlir::LogicalResult CIRToLLVMUnreachableOpLowering::matchAndRewrite( + cir::UnreachableOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + rewriter.replaceOpWithNewOp<mlir::LLVM::UnreachableOp>(op); + return mlir::success(); +} + mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite( cir::TrapOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h index f339d4310ae0c..c5106cb33f452 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h @@ -402,6 +402,16 @@ class CIRToLLVMGetMemberOpLowering mlir::ConversionPatternRewriter &) const override; }; +class CIRToLLVMUnreachableOpLowering + : public mlir::OpConversionPattern<cir::UnreachableOp> { +public: + using mlir::OpConversionPattern<cir::UnreachableOp>::OpConversionPattern; + + mlir::LogicalResult + matchAndRewrite(cir::UnreachableOp op, OpAdaptor, + mlir::ConversionPatternRewriter &) const override; +}; + class CIRToLLVMTrapOpLowering : public mlir::OpConversionPattern<cir::TrapOp> { public: using mlir::OpConversionPattern<cir::TrapOp>::OpConversionPattern; diff --git a/clang/test/CIR/CodeGen/builtin_call.cpp b/clang/test/CIR/CodeGen/builtin_call.cpp index d9a70683a4dbc..c266f1a6d1637 100644 --- a/clang/test/CIR/CodeGen/builtin_call.cpp +++ b/clang/test/CIR/CodeGen/builtin_call.cpp @@ -166,3 +166,63 @@ void expect_prob(int x, int y) { // LLVM-NEXT: %[[Y_LONG:.+]] = sext i32 %[[Y]] to i64 // LLVM-NEXT: %{{.+}} = call i64 @llvm.expect.with.probability.i64(i64 %[[X_LONG]], i64 %[[Y_LONG]], double 2.500000e-01) // LLVM: } + +void unreachable() { + __builtin_unreachable(); +} + +// CIR-LABEL: @_Z11unreachablev +// CIR: cir.unreachable +// CIR: } + +// LLVM-LABEL: @_Z11unreachablev +// LLVM: unreachable +// LLVM: } + +void f1(); +void unreachable2() { + __builtin_unreachable(); + f1(); +} + +// CIR-LABEL: @_Z12unreachable2v +// CIR: cir.unreachable +// CIR-NEXT: ^{{.+}}: +// CIR-NEXT: cir.call @_Z2f1v() : () -> () +// CIR: } + +// LLVM-LABEL: @_Z12unreachable2v +// LLVM: unreachable +// LLVM: {{.+}}: +// LLVM-NEXT: call void @_Z2f1v() +// LLVM: } + +void trap() { + __builtin_trap(); +} + +// CIR-LABEL: @_Z4trapv +// CIR: cir.trap +// CIR: } + +// LLVM-LABEL: @_Z4trapv +// LLVM: call void @llvm.trap() +// LLVM: } + +void trap2() { + __builtin_trap(); + f1(); +} + +// CIR-LABEL: @_Z5trap2v +// CIR: cir.trap +// CIR-NEXT: ^{{.+}}: +// CIR-NEXT: cir.call @_Z2f1v() : () -> () +// CIR: } + +// LLVM-LABEL: @_Z5trap2v +// LLVM: call void @llvm.trap() +// LLVM-NEXT: unreachable +// LLVM: {{.+}}: +// LLVM-NEXT: call void @_Z2f1v() +// LLVM: } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits