diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index 9022d3f3577c..e9985d3329d6 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -1841,8 +1841,37 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, llvm_unreachable("BI__builtin_unwind_init NYI"); case Builtin::BI__builtin_extend_pointer: llvm_unreachable("BI__builtin_extend_pointer NYI"); - case Builtin::BI__builtin_setjmp: - llvm_unreachable("BI__builtin_setjmp NYI"); + case Builtin::BI__builtin_setjmp: { + Address buf = emitPointerWithAlignment(E->getArg(0)); + mlir::Location loc = getLoc(E->getExprLoc()); + + cir::PointerType ppTy = builder.getPointerTo(builder.getVoidPtrTy()); + mlir::Value castBuf = builder.createBitcast(buf.getPointer(), ppTy); + + assert(!cir::MissingFeatures::emitCheckedInBoundsGEP()); + if (getTarget().getTriple().isSystemZ()) { + llvm_unreachable("SYSTEMZ NYI"); + } + + mlir::Value frameaddress = + cir::FrameAddrOp::create(builder, loc, builder.getVoidPtrTy(), + mlir::ValueRange{builder.getUInt32(0, loc)}) + .getResult(); + + cir::StoreOp::create(builder, loc, frameaddress, castBuf); + mlir::Value stacksave = + cir::StackSaveOp::create(builder, loc, builder.getVoidPtrTy()) + .getResult(); + cir::PtrStrideOp stackSaveSlot = cir::PtrStrideOp::create( + builder, loc, ppTy, castBuf, builder.getSInt32(2, loc)); + cir::StoreOp::create(builder, loc, stacksave, stackSaveSlot); + mlir::Value setjmpCall = + cir::LLVMIntrinsicCallOp::create( + builder, loc, builder.getStringAttr("eh.sjlj.setjmp"), + builder.getSInt32Ty(), mlir::ValueRange{castBuf}) + .getResult(); + return RValue::get(setjmpCall); + } case Builtin::BI__builtin_longjmp: llvm_unreachable("BI__builtin_longjmp NYI"); case Builtin::BI__builtin_launder: { @@ -2334,9 +2363,17 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, case Builtin::BI_setjmpex: llvm_unreachable("BI_setjmpex NYI"); break; - case Builtin::BI_setjmp: - llvm_unreachable("BI_setjmp NYI"); + case Builtin::BI_setjmp: { + if (getTarget().getTriple().isOSMSVCRT() && E->getNumArgs() == 1 && + E->getArg(0)->getType()->isPointerType()) { + if (getTarget().getTriple().getArch() == llvm::Triple::x86) + llvm_unreachable("NYI setjmp on x86"); + else if (getTarget().getTriple().getArch() == llvm::Triple::aarch64) + llvm_unreachable("NYI setjmp on aarch64"); + llvm_unreachable("NYI setjmp on generic MSVCRT"); + } break; + } // C++ std:: builtins. case Builtin::BImove: diff --git a/clang/test/CIR/CodeGen/builtin-setjmp-longjmp.c b/clang/test/CIR/CodeGen/builtin-setjmp-longjmp.c new file mode 100644 index 000000000000..fb3cf9637472 --- /dev/null +++ b/clang/test/CIR/CodeGen/builtin-setjmp-longjmp.c @@ -0,0 +1,64 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux -O2 -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux -O2 -fclangir -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s -check-prefix=LLVM +// RUN: %clang_cc1 -triple x86_64-unknown-linux -O2 -emit-llvm %s -o %t.ll +// RUN: FileCheck --input-file=%t.ll %s -check-prefix=OGCG +void test_setjmp(void *env) { + + // CIR-LABEL: test_setjmp + // CIR-SAME: [[ENV:%.*]]: + // CIR-NEXT: [[ENV_ALLOCA:%[0-9]+]] = cir.alloca !cir.ptr, !cir.ptr>, + // CIR-NEXT: cir.store [[ENV]], [[ENV_ALLOCA]] : !cir.ptr, !cir.ptr> + // CIR-NEXT: [[ENV_LOAD:%[0-9]+]] = cir.load align(8) [[ENV_ALLOCA]] + // CIR-NEXT: [[CAST:%[0-9]+]] = cir.cast(bitcast, [[ENV_LOAD]] : !cir.ptr), !cir.ptr> + // CIR-NEXT: [[ZERO:%[0-9]+]] = cir.const #cir.int<0> + // CIR-NEXT: [[FA:%[0-9]+]] = cir.frame_address([[ZERO]]) + // CIR-NEXT: cir.store [[FA]], [[CAST]] : !cir.ptr, !cir.ptr> + // CIR-NEXT: [[SS:%[0-9]+]] = cir.stack_save + // CIR-NEXT: [[TWO:%[0-9]+]] = cir.const #cir.int<2> + // CIR-NEXT: [[GEP:%[0-9]+]] = cir.ptr_stride([[CAST]] : !cir.ptr>, [[TWO]] : !s32i), + // CIR-NEXT: cir.store [[SS]], [[GEP]] : !cir.ptr, !cir.ptr> + // CIR-NEXT: [[SJ:%[0-9]+]] = cir.llvm.intrinsic "eh.sjlj.setjmp" [[CAST]] + + + // LLVM-LABEL: test_setjmp + // LLVM-SAME: (ptr{{.*}}[[ENV:%.*]]) + // LLVM-NEXT: [[FA:%[0-9]+]] = {{.*}}@llvm.frameaddress.p0(i32 0) + // LLVM-NEXT: store ptr [[FA]], ptr [[ENV]] + // LLVM-NEXT: [[SS:%[0-9]+]] = {{.*}}@llvm.stacksave.p0() + // LLVM-NEXT: [[GEP:%[0-9]+]] = getelementptr i8, ptr [[ENV]], i64 16 + // LLVM-NEXT: store ptr [[SS]], ptr [[GEP]] + // LLVM-NEXT: @llvm.eh.sjlj.setjmp(ptr{{.*}}[[ENV]]) + + // OGCG-LABEL: test_setjmp + // OGCG-SAME: (ptr{{.*}}[[ENV:%.*]]) + // OGCG: [[FA:%.*]] = {{.*}}@llvm.frameaddress.p0(i32 0) + // OGCG-NEXT: store ptr [[FA]], ptr [[ENV]] + // OGCG-NEXT: [[SS:%.*]] = {{.*}}@llvm.stacksave.p0() + // OGCG-NEXT: [[GEP:%.*]] = getelementptr inbounds nuw i8, ptr [[ENV]], i64 16 + // OGCG-NEXT: store ptr [[SS]], ptr [[GEP]] + // OGCG-NEXT: @llvm.eh.sjlj.setjmp(ptr{{.*}}[[ENV]]) + __builtin_setjmp(env); +} + +extern int _setjmp(void *env); +void test_setjmp2(void *env) { + + // CIR-LABEL: test_setjmp2 + // CIR-SAME: [[ENV:%.*]]: !cir.ptr + // CIR-NEXT: [[ENV_ALLOCA:%.*]] = cir.alloca + // CIR-NEXT: cir.store [[ENV]], [[ENV_ALLOCA]] + // CIR-NEXT: [[DEAD_GET_GLOBAL:%.*]] = cir.get_global @_setjmp + // CIR-NEXT: [[ENV_LOAD:%.*]] = cir.load align(8) [[ENV_ALLOCA]] + // CIR-NEXT: cir.call @_setjmp([[ENV_LOAD]]) + + // LLVM-LABEL: test_setjmp2 + // LLVM-SAME: (ptr{{.*}}[[ENV:%.*]]) + // LLVM-NEXT: call i32 @_setjmp(ptr [[ENV]]) + // + // OGCG-LABEL: test_setjmp2 + // OGCG-SAME: (ptr{{.*}}[[ENV:%.*]]) + // OGCG: call i32 @_setjmp(ptr noundef [[ENV]]) + _setjmp (env); +}