Skip to content

Commit 8f9ec79

Browse files
committed
[CIR] Add CIRGen for cir.unreachable and cir.trap
1 parent 730d05b commit 8f9ec79

File tree

7 files changed

+123
-1
lines changed

7 files changed

+123
-1
lines changed

clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "mlir/Support/LLVM.h"
2222
#include "clang/AST/Expr.h"
2323
#include "clang/AST/GlobalDecl.h"
24+
#include "clang/Basic/Builtins.h"
2425
#include "clang/CIR/MissingFeatures.h"
2526
#include "llvm/Support/ErrorHandling.h"
2627

@@ -269,6 +270,14 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID,
269270
case Builtin::BI__builtin_rotateright32:
270271
case Builtin::BI__builtin_rotateright64:
271272
return emitRotate(e, /*isRotateLeft=*/false);
273+
274+
case Builtin::BI__builtin_trap:
275+
emitTrap(loc, /*createNewBlock=*/true);
276+
return RValue::get(nullptr);
277+
278+
case Builtin::BI__builtin_unreachable:
279+
emitUnreachable(e->getExprLoc(), /*createNewBlock=*/true);
280+
return RValue::get(nullptr);
272281
}
273282

274283
// If this is an alias for a lib function (e.g. __builtin_sin), emit

clang/lib/CIR/CodeGen/CIRGenExpr.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1780,6 +1780,20 @@ LValue CIRGenFunction::emitLoadOfReferenceLValue(Address refAddr,
17801780
pointeeBaseInfo);
17811781
}
17821782

1783+
void CIRGenFunction::emitTrap(mlir::Location loc, bool createNewBlock) {
1784+
cir::TrapOp::create(builder, loc);
1785+
if (createNewBlock)
1786+
builder.createBlock(builder.getBlock()->getParent());
1787+
}
1788+
1789+
void CIRGenFunction::emitUnreachable(clang::SourceLocation loc,
1790+
bool createNewBlock) {
1791+
assert(!cir::MissingFeatures::sanitizers());
1792+
cir::UnreachableOp::create(builder, getLoc(loc));
1793+
if (createNewBlock)
1794+
builder.createBlock(builder.getBlock()->getParent());
1795+
}
1796+
17831797
mlir::Value CIRGenFunction::createDummyValue(mlir::Location loc,
17841798
clang::QualType qt) {
17851799
mlir::Type t = convertType(qt);

clang/lib/CIR/CodeGen/CIRGenFunction.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,7 @@ void CIRGenFunction::LexicalScope::emitImplicitReturn() {
382382
!mayDropFunctionReturn(fd->getASTContext(), fd->getReturnType());
383383

384384
if (shouldEmitUnreachable) {
385+
assert(!cir::MissingFeatures::sanitizers());
385386
if (cgf.cgm.getCodeGenOpts().OptimizationLevel == 0)
386387
builder.create<cir::TrapOp>(localScope->endLoc);
387388
else

clang/lib/CIR/CodeGen/CIRGenFunction.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1199,8 +1199,28 @@ class CIRGenFunction : public CIRGenTypeCache {
11991199
/// to conserve the high level information.
12001200
mlir::Value emitToMemory(mlir::Value value, clang::QualType ty);
12011201

1202+
/// Emit a trap instruction, which is used to abort the program in an abnormal
1203+
/// way, usually for debugging purposes.
1204+
/// \p createNewBlock indicates whether to create a new block for the IR
1205+
/// builder. Since the `cir.trap` operation is a terminator, operations that
1206+
/// follow a trap cannot be emitted after `cir.trap` in the same block. To
1207+
/// ensure these operations get emitted successfully, you need to create a new
1208+
/// dummy block and set the insertion point there before continuing from the
1209+
/// trap operation.
1210+
void emitTrap(mlir::Location loc, bool createNewBlock);
1211+
12021212
LValue emitUnaryOpLValue(const clang::UnaryOperator *e);
12031213

1214+
/// Emit a reached-unreachable diagnostic if \p loc is valid and runtime
1215+
/// checking is enabled. Otherwise, just emit an unreachable instruction.
1216+
/// \p createNewBlock indicates whether to create a new block for the IR
1217+
/// builder. Since the `cir.unreachable` operation is a terminator, operations
1218+
/// that follow an unreachable point cannot be emitted after `cir.unreachable`
1219+
/// in the same block. To ensure these operations get emitted successfully,
1220+
/// you need to create a dummy block and set the insertion point there before
1221+
/// continuing from the unreachable point.
1222+
void emitUnreachable(clang::SourceLocation loc, bool createNewBlock);
1223+
12041224
/// This method handles emission of any variable declaration
12051225
/// inside a function, including static vars etc.
12061226
void emitVarDecl(const clang::VarDecl &d);

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2214,7 +2214,8 @@ void ConvertCIRToLLVMPass::runOnOperation() {
22142214
CIRToLLVMVecShuffleDynamicOpLowering,
22152215
CIRToLLVMVecShuffleOpLowering,
22162216
CIRToLLVMVecSplatOpLowering,
2217-
CIRToLLVMVecTernaryOpLowering
2217+
CIRToLLVMVecTernaryOpLowering,
2218+
CIRToLLVMUnreachableOpLowering
22182219
// clang-format on
22192220
>(converter, patterns.getContext());
22202221

@@ -2270,6 +2271,13 @@ mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite(
22702271
}
22712272
}
22722273

2274+
mlir::LogicalResult CIRToLLVMUnreachableOpLowering::matchAndRewrite(
2275+
cir::UnreachableOp op, OpAdaptor adaptor,
2276+
mlir::ConversionPatternRewriter &rewriter) const {
2277+
rewriter.replaceOpWithNewOp<mlir::LLVM::UnreachableOp>(op);
2278+
return mlir::success();
2279+
}
2280+
22732281
mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
22742282
cir::TrapOp op, OpAdaptor adaptor,
22752283
mlir::ConversionPatternRewriter &rewriter) const {

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,16 @@ class CIRToLLVMGetMemberOpLowering
402402
mlir::ConversionPatternRewriter &) const override;
403403
};
404404

405+
class CIRToLLVMUnreachableOpLowering
406+
: public mlir::OpConversionPattern<cir::UnreachableOp> {
407+
public:
408+
using mlir::OpConversionPattern<cir::UnreachableOp>::OpConversionPattern;
409+
410+
mlir::LogicalResult
411+
matchAndRewrite(cir::UnreachableOp op, OpAdaptor,
412+
mlir::ConversionPatternRewriter &) const override;
413+
};
414+
405415
class CIRToLLVMTrapOpLowering : public mlir::OpConversionPattern<cir::TrapOp> {
406416
public:
407417
using mlir::OpConversionPattern<cir::TrapOp>::OpConversionPattern;

clang/test/CIR/CodeGen/builtin_call.cpp

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,3 +166,63 @@ void expect_prob(int x, int y) {
166166
// LLVM-NEXT: %[[Y_LONG:.+]] = sext i32 %[[Y]] to i64
167167
// LLVM-NEXT: %{{.+}} = call i64 @llvm.expect.with.probability.i64(i64 %[[X_LONG]], i64 %[[Y_LONG]], double 2.500000e-01)
168168
// LLVM: }
169+
170+
void unreachable() {
171+
__builtin_unreachable();
172+
}
173+
174+
// CIR-LABEL: @_Z11unreachablev
175+
// CIR: cir.unreachable
176+
// CIR: }
177+
178+
// LLVM-LABEL: @_Z11unreachablev
179+
// LLVM: unreachable
180+
// LLVM: }
181+
182+
void f1();
183+
void unreachable2() {
184+
__builtin_unreachable();
185+
f1();
186+
}
187+
188+
// CIR-LABEL: @_Z12unreachable2v
189+
// CIR: cir.unreachable
190+
// CIR-NEXT: ^{{.+}}:
191+
// CIR-NEXT: cir.call @_Z2f1v() : () -> ()
192+
// CIR: }
193+
194+
// LLVM-LABEL: @_Z12unreachable2v
195+
// LLVM: unreachable
196+
// LLVM: {{.+}}:
197+
// LLVM-NEXT: call void @_Z2f1v()
198+
// LLVM: }
199+
200+
void trap() {
201+
__builtin_trap();
202+
}
203+
204+
// CIR-LABEL: @_Z4trapv
205+
// CIR: cir.trap
206+
// CIR: }
207+
208+
// LLVM-LABEL: @_Z4trapv
209+
// LLVM: call void @llvm.trap()
210+
// LLVM: }
211+
212+
void trap2() {
213+
__builtin_trap();
214+
f1();
215+
}
216+
217+
// CIR-LABEL: @_Z5trap2v
218+
// CIR: cir.trap
219+
// CIR-NEXT: ^{{.+}}:
220+
// CIR-NEXT: cir.call @_Z2f1v() : () -> ()
221+
// CIR: }
222+
223+
// LLVM-LABEL: @_Z5trap2v
224+
// LLVM: call void @llvm.trap()
225+
// LLVM-NEXT: unreachable
226+
// LLVM: {{.+}}:
227+
// LLVM-NEXT: call void @_Z2f1v()
228+
// LLVM: }

0 commit comments

Comments
 (0)