-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[CIR] Add CIRGen for cir.unreachable and cir.trap #151363
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clangir Author: Sirui Mu (Lancern) ChangesThis patch adds CIRGen support for Full diff: https://github.com/llvm/llvm-project/pull/151363.diff 6 Files Affected:
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
index 9049a016b2b9b..735b2b0a1627d 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,22 @@ 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: {
+ builder.create<cir::TrapOp>(loc);
+ // Note that cir.trap is a terminator so we need to start a new dummy block
+ // to preserve the builder's insertion point.
+ builder.createBlock(builder.getBlock()->getParent());
+ return RValue::get(nullptr);
+ }
+
+ case Builtin::BI__builtin_unreachable: {
+ emitUnreachable(e->getExprLoc());
+ // Note that cir.unreachable is a terminator so we need to start a new dummy
+ // block to preserve the builder's insertion point.
+ builder.createBlock(builder.getBlock()->getParent());
+ 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..ae8da71219bf3 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -1780,6 +1780,11 @@ LValue CIRGenFunction::emitLoadOfReferenceLValue(Address refAddr,
pointeeBaseInfo);
}
+void CIRGenFunction::emitUnreachable(clang::SourceLocation loc) {
+ assert(!cir::MissingFeatures::sanitizers());
+ builder.create<cir::UnreachableOp>(getLoc(loc));
+}
+
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..01049424f90cb 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -1201,6 +1201,10 @@ class CIRGenFunction : public CIRGenTypeCache {
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.
+ void emitUnreachable(clang::SourceLocation loc);
+
/// 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..8465ea83d7875 100644
--- a/clang/test/CIR/CodeGen/builtin_call.cpp
+++ b/clang/test/CIR/CodeGen/builtin_call.cpp
@@ -166,3 +166,27 @@ 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 trap() {
+ __builtin_trap();
+}
+
+// CIR-LABEL: @_Z4trapv
+// CIR: cir.trap
+// CIR: }
+
+// LLVM-LABEL: @_Z4trapv
+// LLVM: call void @llvm.trap()
+// LLVM: }
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exercise this in tests, so that additional block is really required. Same for unreachable below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also is this really needed? Classic codegen adds additional block only for unreachable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also it is unclear to me why this one is inlined while unreachable uses emitUnreachable as in classic codegen. We should probably add emitTrap too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also is this really needed? Classic codegen adds additional block only for unreachable.
In the classic CodeGen, calls to __builtin_unreachable gets lowered to the unreachable instruction, and calls to __builtin_trap gets lowered to an intrinsic call to @llvm.trap(). The former is a terminator instruction, which prohibits any further instructions from following it in the same block. The latter is not a terminator and it could be followed by more instructions in the same block (these instructions would be DCE-ed though). So in the classic CodeGen we don't have to start a new block after calling __builtin_trap.
On the contrary, in CIR world, both of cir.unreachable and cir.trap are terminators. Thus we have to start a new block after them to hold those instructions that follow them.
Also it is unclear to me why this one is inlined while unreachable uses emitUnreachable as in classic codegen. We should probably add emitTrap too.
emitUnreachable is there because we have a sanitizer for unreachable code. We don't have sanitizers for traps, so we just inlined the creation of cir.trap.
Maybe we could put builder.createBlock in emitUnreachable and emitTrap though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we could put builder.createBlock in emitUnreachable and emitTrap though.
I updated code like this.
22fd432 to
8f1deb8
Compare
andykaylor
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm, with a couple of minor comments
8f1deb8 to
6e74f19
Compare
6e74f19 to
8f9ec79
Compare
xlauko
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
This patch adds CIRGen support for
cir.unreachableandcir.trap. It also adds missing LLVM lowering code forcir.unreachable.