Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
29 changes: 29 additions & 0 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -4698,6 +4698,35 @@ def CIR_EhTypeIdOp : CIR_Op<"eh.typeid",
}];
}

def CIR_EhSetjmp : CIR_Op<"eh.setjmp"> {
let summary = "CIR setjmp operation";
let description = [{
Saves various information about the calling
environment (typically, the stack pointer, the instruction
pointer, possibly the values of other registers and the signal
mask) in the buffer env for later use by longjmp(). In this case,
setjmp() returns 0. When retuned from a longjmp(), setjmp returns the
value passed into longjmp().

Examples:
```mlir
// Specify setjmp is builtin
%0 = cir.eh.setjmp %arg0 : !p32, builtin -> !s32i

// Specify setjmp is not builtin
%0 = cir.eh.setjmp %arg0 : !p32 -> !s32i
```
}];

let arguments = (ins CIR_PointerType:$buf, UnitAttr:$builtin);
let results = (outs CIR_SInt32:$res);
let assemblyFormat = [{
$buf `:` type($buf)
(`,` `builtin` $builtin^)?
`->` type(results) attr-dict
}];
}

//===----------------------------------------------------------------------===//
// CopyOp
//===----------------------------------------------------------------------===//
Expand Down
22 changes: 22 additions & 0 deletions clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4288,6 +4288,27 @@ mlir::LogicalResult CIRToLLVMEhTypeIdOpLowering::matchAndRewrite(
return mlir::success();
}

mlir::LogicalResult CIRToLLVMEhSetjmpOpLowering::matchAndRewrite(
cir::EhSetjmp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
mlir::Type returnType = typeConverter->convertType(op.getType());
if (op.getBuiltinAttr()) {
mlir::LLVM::CallIntrinsicOp newOp =
createCallLLVMIntrinsicOp(rewriter, op.getLoc(), "llvm.eh.sjlj.setjmp",
returnType, adaptor.getBuf());
rewriter.replaceOp(op, newOp);
} else {
StringRef fnName = "_setjmp";
auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
auto fnType = mlir::LLVM::LLVMFunctionType::get(returnType, llvmPtrTy,
/*isVarArg=*/false);
getOrCreateLLVMFuncOp(rewriter, op, fnName, fnType);
rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(op, returnType, fnName,
adaptor.getBuf());
}
return mlir::success();
}

mlir::LogicalResult CIRToLLVMCatchParamOpLowering::matchAndRewrite(
cir::CatchParamOp op, OpAdaptor adaptor,
mlir::ConversionPatternRewriter &rewriter) const {
Expand Down Expand Up @@ -4531,6 +4552,7 @@ void populateCIRToLLVMConversionPatterns(
CIRToLLVMDerivedClassAddrOpLowering,
CIRToLLVMEhInflightOpLowering,
CIRToLLVMEhTypeIdOpLowering,
CIRToLLVMEhSetjmpOpLowering,
CIRToLLVMExpectOpLowering,
CIRToLLVMExtractMemberOpLowering,
CIRToLLVMFrameAddrOpLowering,
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 @@ -1220,6 +1220,16 @@ class CIRToLLVMEhTypeIdOpLowering
mlir::ConversionPatternRewriter &) const override;
};

class CIRToLLVMEhSetjmpOpLowering
: public mlir::OpConversionPattern<cir::EhSetjmp> {
public:
using mlir::OpConversionPattern<cir::EhSetjmp>::OpConversionPattern;

mlir::LogicalResult
matchAndRewrite(cir::EhSetjmp op, OpAdaptor,
mlir::ConversionPatternRewriter &) const override;
};

class CIRToLLVMCatchParamOpLowering
: public mlir::OpConversionPattern<cir::CatchParamOp> {
public:
Expand Down
28 changes: 28 additions & 0 deletions clang/test/CIR/Lowering/setjmp-longjmp.cir
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// RUN: cir-opt %s -cir-to-llvm -o %t.ll
// RUN: FileCheck %s --input-file=%t.ll -check-prefix=MLIR
!s32i = !cir.int<s, 32>
!p32 = !cir.ptr<!s32i>

module {
// MLIR: module {
cir.func @test_setjmp(%arg0 : !p32) -> !s32i {

// MLIR: llvm.func @test_setjmp([[ARG0:%.*]]: !llvm.ptr) -> i32
// MLIR-NEXT: [[RET:%.*]] = llvm.call_intrinsic "llvm.eh.sjlj.setjmp"([[ARG0]]) : (!llvm.ptr) -> i32
// MLIR-NEXT: llvm.return [[RET:%.*]] : i32
// MLIR-NEXT: }
%0 = cir.eh.setjmp %arg0 : !p32, builtin -> !s32i
cir.return %0 : !s32i
}
cir.func @test_setjmp_2(%arg0 : !p32) -> !s32i {

// MLIR: llvm.func @test_setjmp_2([[ARG0:%.*]]: !llvm.ptr) -> i32
// MLIR-NEXT: [[RET:%.*]] = llvm.call @_setjmp([[ARG0]]) : (!llvm.ptr) -> i32
// MLIR-NEXT: llvm.return [[RET:%.*]] : i32
// MLIR-NEXT: }
%0 = cir.eh.setjmp %arg0 : !p32 -> !s32i
cir.return %0 : !s32i
}
// MLIR: }
}

54 changes: 54 additions & 0 deletions clang/test/CIR/Transforms/setjmp-longjmp-lower.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-lowering-prepare %s -o - 2>&1 | FileCheck %s -check-prefix=BEFORE-LOWERING-PREPARE
// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-after=cir-lowering-prepare %s -o - 2>&1 | FileCheck %s -check-prefix=AFTER-LOWERING-PREPARE
void test_setjmp(void *env) {
// BEFORE-LOWERING-PREPARE-LABEL: test_setjmp
// BEFORE-LOWERING-PREPARE-SAME: [[ENV:%.*]]:
// BEFORE-LOWERING-PREPARE-NEXT: [[ENV_ALLOCA:%[0-9]+]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>,
// BEFORE-LOWERING-PREPARE-NEXT: cir.store [[ENV]], [[ENV_ALLOCA]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
// BEFORE-LOWERING-PREPARE-NEXT: [[ENV_LOAD:%[0-9]+]] = cir.load align(8) [[ENV_ALLOCA]]
// BEFORE-LOWERING-PREPARE-NEXT: [[CAST:%[0-9]+]] = cir.cast(bitcast, [[ENV_LOAD]] : !cir.ptr<!void>), !cir.ptr<!cir.ptr<!void>>
// BEFORE-LOWERING-PREPARE-NEXT: [[ZERO:%[0-9]+]] = cir.const #cir.int<0>
// BEFORE-LOWERING-PREPARE-NEXT: [[FA:%[0-9]+]] = cir.frame_address([[ZERO]])
// BEFORE-LOWERING-PREPARE-NEXT: cir.store [[FA]], [[CAST]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
// BEFORE-LOWERING-PREPARE-NEXT: [[SS:%[0-9]+]] = cir.stack_save
// BEFORE-LOWERING-PREPARE-NEXT: [[TWO:%[0-9]+]] = cir.const #cir.int<2>
// BEFORE-LOWERING-PREPARE-NEXT: [[GEP:%[0-9]+]] = cir.ptr_stride([[CAST]] : !cir.ptr<!cir.ptr<!void>>, [[TWO]] : !s32i),
// BEFORE-LOWERING-PREPARE-NEXT: cir.store [[SS]], [[GEP]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
// BEFORE-LOWERING-PREPARE-NEXT: [[SJ:%[0-9]+]] = cir.llvm.intrinsic "eh.sjlj.setjmp" [[CAST]]

// AFTER-LOWERING-PREPARE-LABEL: test_setjmp
// AFTER-LOWERING-PREPARE-SAME: [[ENV:%.*]]:
// AFTER-LOWERING-PREPARE-NEXT: [[ENV_ALLOCA:%[0-9]+]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>,
// AFTER-LOWERING-PREPARE-NEXT: cir.store [[ENV]], [[ENV_ALLOCA]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
// AFTER-LOWERING-PREPARE-NEXT: [[ENV_LOAD:%[0-9]+]] = cir.load align(8) [[ENV_ALLOCA]]
// AFTER-LOWERING-PREPARE-NEXT: [[CAST:%[0-9]+]] = cir.cast(bitcast, [[ENV_LOAD]] : !cir.ptr<!void>), !cir.ptr<!cir.ptr<!void>>
// AFTER-LOWERING-PREPARE-NEXT: [[ZERO:%[0-9]+]] = cir.const #cir.int<0>
// AFTER-LOWERING-PREPARE-NEXT: [[FA:%[0-9]+]] = cir.frame_address([[ZERO]])
// AFTER-LOWERING-PREPARE-NEXT: cir.store [[FA]], [[CAST]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
// AFTER-LOWERING-PREPARE-NEXT: [[SS:%[0-9]+]] = cir.stack_save
// AFTER-LOWERING-PREPARE-NEXT: [[TWO:%[0-9]+]] = cir.const #cir.int<2>
// AFTER-LOWERING-PREPARE-NEXT: [[GEP:%[0-9]+]] = cir.ptr_stride([[CAST]] : !cir.ptr<!cir.ptr<!void>>, [[TWO]] : !s32i),
// AFTER-LOWERING-PREPARE-NEXT: cir.store [[SS]], [[GEP]] : !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>
// AFTER-LOWERING-PREPARE-NEXT: [[SJ:%[0-9]+]] = cir.llvm.intrinsic "eh.sjlj.setjmp" [[CAST]]
__builtin_setjmp(env);
}

extern int _setjmp(void *env);
void test_setjmp2(void *env) {
// BEFORE-LOWERING-PREPARE-LABEL: test_setjmp2
// BEFORE-LOWERING-PREPARE-SAME: [[ENV:%.*]]: !cir.ptr<!void>
// BEFORE-LOWERING-PREPARE-NEXT: [[ENV_ALLOCA:%.*]] = cir.alloca
// BEFORE-LOWERING-PREPARE-NEXT: cir.store [[ENV]], [[ENV_ALLOCA]]
// BEFORE-LOWERING-PREPARE-NEXT: [[DEAD_GET_GLOBAL:%.*]] = cir.get_global @_setjmp
// BEFORE-LOWERING-PREPARE-NEXT: [[ENV_LOAD:%.*]] = cir.load align(8) [[ENV_ALLOCA]]
// BEFORE-LOWERING-PREPARE-NEXT: cir.call @_setjmp([[ENV_LOAD]])

// AFTER-LOWERING-PREPARE-LABEL: test_setjmp2
// AFTER-LOWERING-PREPARE-SAME: [[ENV:%.*]]: !cir.ptr<!void>
// AFTER-LOWERING-PREPARE-NEXT: [[ENV_ALLOCA:%.*]] = cir.alloca
// AFTER-LOWERING-PREPARE-NEXT: cir.store [[ENV]], [[ENV_ALLOCA]]
// AFTER-LOWERING-PREPARE-NEXT: [[DEAD_GET_GLOBAL:%.*]] = cir.get_global @_setjmp
// AFTER-LOWERING-PREPARE-NEXT: [[ENV_LOAD:%.*]] = cir.load align(8) [[ENV_ALLOCA]]
// AFTER-LOWERING-PREPARE-NEXT: cir.call @_setjmp([[ENV_LOAD]])
_setjmp (env);
}
Loading