Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"

Expand Down Expand Up @@ -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
Expand Down
14 changes: 14 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions clang/lib/CIR/CodeGen/CIRGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,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
Expand Down
20 changes: 20 additions & 0 deletions clang/lib/CIR/CodeGen/CIRGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
10 changes: 9 additions & 1 deletion clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2214,7 +2214,8 @@ void ConvertCIRToLLVMPass::runOnOperation() {
CIRToLLVMVecShuffleDynamicOpLowering,
CIRToLLVMVecShuffleOpLowering,
CIRToLLVMVecSplatOpLowering,
CIRToLLVMVecTernaryOpLowering
CIRToLLVMVecTernaryOpLowering,
CIRToLLVMUnreachableOpLowering
// clang-format on
>(converter, patterns.getContext());

Expand Down Expand Up @@ -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 {
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
60 changes: 60 additions & 0 deletions clang/test/CIR/CodeGen/builtin_call.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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: }