Skip to content

Commit 13600c7

Browse files
authored
[CIR] Add CIRGen for cir.unreachable and cir.trap (#151363)
1 parent 94d374a commit 13600c7

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
@@ -1939,6 +1939,20 @@ LValue CIRGenFunction::emitLoadOfReferenceLValue(Address refAddr,
19391939
pointeeBaseInfo);
19401940
}
19411941

1942+
void CIRGenFunction::emitTrap(mlir::Location loc, bool createNewBlock) {
1943+
cir::TrapOp::create(builder, loc);
1944+
if (createNewBlock)
1945+
builder.createBlock(builder.getBlock()->getParent());
1946+
}
1947+
1948+
void CIRGenFunction::emitUnreachable(clang::SourceLocation loc,
1949+
bool createNewBlock) {
1950+
assert(!cir::MissingFeatures::sanitizers());
1951+
cir::UnreachableOp::create(builder, getLoc(loc));
1952+
if (createNewBlock)
1953+
builder.createBlock(builder.getBlock()->getParent());
1954+
}
1955+
19421956
mlir::Value CIRGenFunction::createDummyValue(mlir::Location loc,
19431957
clang::QualType qt) {
19441958
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
@@ -383,6 +383,7 @@ void CIRGenFunction::LexicalScope::emitImplicitReturn() {
383383
!mayDropFunctionReturn(fd->getASTContext(), fd->getReturnType());
384384

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

clang/lib/CIR/CodeGen/CIRGenFunction.h

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

1226+
/// Emit a trap instruction, which is used to abort the program in an abnormal
1227+
/// way, usually for debugging purposes.
1228+
/// \p createNewBlock indicates whether to create a new block for the IR
1229+
/// builder. Since the `cir.trap` operation is a terminator, operations that
1230+
/// follow a trap cannot be emitted after `cir.trap` in the same block. To
1231+
/// ensure these operations get emitted successfully, you need to create a new
1232+
/// dummy block and set the insertion point there before continuing from the
1233+
/// trap operation.
1234+
void emitTrap(mlir::Location loc, bool createNewBlock);
1235+
12261236
LValue emitUnaryOpLValue(const clang::UnaryOperator *e);
12271237

1238+
/// Emit a reached-unreachable diagnostic if \p loc is valid and runtime
1239+
/// checking is enabled. Otherwise, just emit an unreachable instruction.
1240+
/// \p createNewBlock indicates whether to create a new block for the IR
1241+
/// builder. Since the `cir.unreachable` operation is a terminator, operations
1242+
/// that follow an unreachable point cannot be emitted after `cir.unreachable`
1243+
/// in the same block. To ensure these operations get emitted successfully,
1244+
/// you need to create a dummy block and set the insertion point there before
1245+
/// continuing from the unreachable point.
1246+
void emitUnreachable(clang::SourceLocation loc, bool createNewBlock);
1247+
12281248
/// This method handles emission of any variable declaration
12291249
/// inside a function, including static vars etc.
12301250
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
@@ -2212,7 +2212,8 @@ void ConvertCIRToLLVMPass::runOnOperation() {
22122212
CIRToLLVMVecShuffleDynamicOpLowering,
22132213
CIRToLLVMVecShuffleOpLowering,
22142214
CIRToLLVMVecSplatOpLowering,
2215-
CIRToLLVMVecTernaryOpLowering
2215+
CIRToLLVMVecTernaryOpLowering,
2216+
CIRToLLVMUnreachableOpLowering
22162217
// clang-format on
22172218
>(converter, patterns.getContext());
22182219

@@ -2268,6 +2269,13 @@ mlir::LogicalResult CIRToLLVMGetMemberOpLowering::matchAndRewrite(
22682269
}
22692270
}
22702271

2272+
mlir::LogicalResult CIRToLLVMUnreachableOpLowering::matchAndRewrite(
2273+
cir::UnreachableOp op, OpAdaptor adaptor,
2274+
mlir::ConversionPatternRewriter &rewriter) const {
2275+
rewriter.replaceOpWithNewOp<mlir::LLVM::UnreachableOp>(op);
2276+
return mlir::success();
2277+
}
2278+
22712279
mlir::LogicalResult CIRToLLVMTrapOpLowering::matchAndRewrite(
22722280
cir::TrapOp op, OpAdaptor adaptor,
22732281
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)