[CIR] Add CIRGen for cir.unreachable and cir.trap (#151363)
This commit is contained in:
parent
94d374ab6c
commit
13600c72ce
@ -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,14 @@ 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
|
||||
|
||||
@ -1939,6 +1939,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);
|
||||
|
||||
@ -383,6 +383,7 @@ void CIRGenFunction::LexicalScope::emitImplicitReturn() {
|
||||
!mayDropFunctionReturn(fd->getASTContext(), fd->getReturnType());
|
||||
|
||||
if (shouldEmitUnreachable) {
|
||||
assert(!cir::MissingFeatures::sanitizers());
|
||||
if (cgf.cgm.getCodeGenOpts().OptimizationLevel == 0)
|
||||
builder.create<cir::TrapOp>(localScope->endLoc);
|
||||
else
|
||||
|
||||
@ -1223,8 +1223,28 @@ public:
|
||||
/// 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);
|
||||
|
||||
@ -2212,7 +2212,8 @@ void ConvertCIRToLLVMPass::runOnOperation() {
|
||||
CIRToLLVMVecShuffleDynamicOpLowering,
|
||||
CIRToLLVMVecShuffleOpLowering,
|
||||
CIRToLLVMVecSplatOpLowering,
|
||||
CIRToLLVMVecTernaryOpLowering
|
||||
CIRToLLVMVecTernaryOpLowering,
|
||||
CIRToLLVMUnreachableOpLowering
|
||||
// clang-format on
|
||||
>(converter, patterns.getContext());
|
||||
|
||||
@ -2268,6 +2269,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 {
|
||||
|
||||
@ -402,6 +402,16 @@ public:
|
||||
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;
|
||||
|
||||
@ -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: }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user