https://github.com/Luhaocong updated https://github.com/llvm/llvm-project/pull/171974
>From 9772a1690ff6d40db9f1263b812f644b095d7e66 Mon Sep 17 00:00:00 2001 From: Haocong Lu <[email protected]> Date: Fri, 12 Dec 2025 13:55:59 +0800 Subject: [PATCH 1/2] [CIR][X86] Implement lowering for `_AddressOfReturnAddress` builtin - Add new `CIR_AddrOfReturnAddrOp` and support lowering it to LLVMIR - Add CIR CodeGen for `_AddressOfReturnAddress` X86 builtin --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 23 +++++++++++ clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp | 7 +++- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 9 +++++ clang/test/CIR/CodeGen/ms-intrinsics.c | 40 +++++++++++++++++++ 4 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 clang/test/CIR/CodeGen/ms-intrinsics.c diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 868b813458aae..256e60c41981e 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -3339,6 +3339,29 @@ def CIR_FrameAddrOp : CIR_FuncAddrBuiltinOp<"frame_address"> { }]; } +//===----------------------------------------------------------------------===// +// AddrOfReturnAddrOp +//===----------------------------------------------------------------------===// + +def CIR_AddrOfReturnAddrOp : CIR_Op<"address_of_return_address"> { + let summary = "The place stores the return address of the current function"; + + let description = [{ + Represents a call to builtin function `_AddressOfReturnAddress` in CIR. + This builtin function returns a pointer to the place in the stack frame + where the return address of the current function is stored. + + Examples: + + ```mlir + %addr = address_of_return_address() : !cir.ptr<!cir.int<u, 8>> + ``` + }]; + + let results = (outs CIR_PointerType:$result); + let assemblyFormat = "attr-dict `:` qualified(type($result))"; +} + //===----------------------------------------------------------------------===// // StackSaveOp & StackRestoreOp //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp index f9e1f75a51143..e876d59bf1677 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp @@ -1706,7 +1706,12 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) { cir::SyncScopeKind::SingleThread)); return mlir::Value{}; } - case X86::BI_AddressOfReturnAddress: + case X86::BI_AddressOfReturnAddress: { + mlir::Location loc = getLoc(expr->getExprLoc()); + mlir::Value addr = + cir::AddrOfReturnAddrOp::create(builder, loc, allocaInt8PtrTy); + return builder.createCast(loc, cir::CastKind::bitcast, addr, voidPtrTy); + } case X86::BI__stosb: case X86::BI__ud2: case X86::BI__int2c: diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 7d854997848aa..73f9e5390b886 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -1653,6 +1653,15 @@ mlir::LogicalResult CIRToLLVMFrameAddrOpLowering::matchAndRewrite( return mlir::success(); } +mlir::LogicalResult CIRToLLVMAddrOfReturnAddrOpLowering::matchAndRewrite( + cir::AddrOfReturnAddrOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType()); + replaceOpWithCallLLVMIntrinsicOp(rewriter, op, "llvm.addressofreturnaddress", + llvmPtrTy, adaptor.getOperands()); + return mlir::success(); +} + mlir::LogicalResult CIRToLLVMLoadOpLowering::matchAndRewrite( cir::LoadOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { diff --git a/clang/test/CIR/CodeGen/ms-intrinsics.c b/clang/test/CIR/CodeGen/ms-intrinsics.c new file mode 100644 index 0000000000000..fa6872c207c92 --- /dev/null +++ b/clang/test/CIR/CodeGen/ms-intrinsics.c @@ -0,0 +1,40 @@ +// RUN: %clang_cc1 -x c -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \ +// RUN: -triple x86_64-unknown-linux -Wno-implicit-function-declaration -fclangir -emit-cir -o %t.cir %s +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s +// RUN: %clang_cc1 -x c++ -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \ +// RUN: -triple x86_64-unknown-linux -Wno-implicit-function-declaration -fclangir -emit-cir -o %t.cir %s +// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s + +// RUN: %clang_cc1 -x c -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \ +// RUN: -triple x86_64-unknown-linux -Wno-implicit-function-declaration -fclangir -emit-llvm -o %t.ll %s +// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s +// RUN: %clang_cc1 -x c++ -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \ +// RUN: -triple x86_64-unknown-linux -Wno-implicit-function-declaration -fclangir -emit-llvm -o %t.ll %s +// RUN: FileCheck --check-prefix=LLVM --input-file=%t.ll %s + +// RUN: %clang_cc1 -x c -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \ +// RUN: -triple x86_64-unknown-linux -emit-llvm -Wall -Werror %s -o - \ +// RUN: | FileCheck %s -check-prefix=OGCG +// RUN: %clang_cc1 -x c++ -ffreestanding -fms-extensions -fms-compatibility -fms-compatibility-version=17.00 \ +// RUN: -triple x86_64-unknown-linux -emit-llvm -Wall -Werror %s -o - \ +// RUN: | FileCheck %s -check-prefix=OGCG + +// This test mimics clang/test/CodeGen/ms-intrinsics.c, which eventually +// CIR shall be able to support fully. + +void *_AddressOfReturnAddress(void); + +#if defined(__i386__) || defined(__x86_64__) || defined (__aarch64__) +void *test_AddressOfReturnAddress(void) { + // CIR-LABEL: test_AddressOfReturnAddress + // CIR: %[[ADDR:.*]] = cir.address_of_return_address : !cir.ptr<!u8i> + // CIR: %{{.*}} = cir.cast bitcast %[[ADDR]] : !cir.ptr<!u8i> -> !cir.ptr<!void> + + // LLVM-LABEL: test_AddressOfReturnAddress + // LLVM: call ptr @llvm.addressofreturnaddress.p0() + + // OGCG-LABEL: test_AddressOfReturnAddress + // OGCG: call ptr @llvm.addressofreturnaddress.p0() + return _AddressOfReturnAddress(); +} +#endif >From 795ab27307ee53278f6a22638ea15a21e1b30a43 Mon Sep 17 00:00:00 2001 From: Haocong Lu <[email protected]> Date: Thu, 18 Dec 2025 16:58:32 +0800 Subject: [PATCH 2/2] [CIR][X86] Fix error return type of FrameAddrOp --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 26 ++++++++--------- clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp | 28 +++++++++++-------- .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 4 +-- clang/test/CIR/CodeGen/ms-intrinsics.c | 16 ++++++++++- clang/test/CIR/CodeGenBuiltins/builtins.cpp | 3 +- 5 files changed, 49 insertions(+), 28 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 256e60c41981e..bda773b41ac5c 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -3281,15 +3281,7 @@ def CIR_CopyOp : CIR_Op<"copy",[ // ReturnAddrOp and FrameAddrOp //===----------------------------------------------------------------------===// -class CIR_FuncAddrBuiltinOp<string mnemonic> : CIR_Op<mnemonic, []> { - let arguments = (ins CIR_UInt32:$level); - let results = (outs CIR_VoidPtrType:$result); - let assemblyFormat = [{ - `(` $level `)` attr-dict - }]; -} - -def CIR_ReturnAddrOp : CIR_FuncAddrBuiltinOp<"return_address"> { +def CIR_ReturnAddrOp : CIR_Op<"return_address"> { let summary = "The return address of the current function, or of one of its callers"; @@ -3306,12 +3298,16 @@ def CIR_ReturnAddrOp : CIR_FuncAddrBuiltinOp<"return_address"> { Examples: ```mlir - %p = return_address(%level) -> !cir.ptr<!void> + %p = return_address(%level) : !cir.ptr<!void> ``` }]; + + let arguments = (ins CIR_UInt32:$level); + let results = (outs CIR_VoidPtrType:$result); + let assemblyFormat = "`(` $level `)` attr-dict"; } -def CIR_FrameAddrOp : CIR_FuncAddrBuiltinOp<"frame_address"> { +def CIR_FrameAddrOp : CIR_Op<"frame_address"> { let summary = "The frame address of the current function, or of one of its callers"; @@ -3334,9 +3330,13 @@ def CIR_FrameAddrOp : CIR_FuncAddrBuiltinOp<"frame_address"> { Examples: ```mlir - %p = frame_address(%level) -> !cir.ptr<!void> + %p = frame_address(%level) : !cir.ptr<!u8i> ``` }]; + + let arguments = (ins CIR_UInt32:$level); + let results = (outs CIR_PointerType:$result); + let assemblyFormat = "`(` $level `)` attr-dict `:` qualified(type($result))"; } //===----------------------------------------------------------------------===// @@ -3354,7 +3354,7 @@ def CIR_AddrOfReturnAddrOp : CIR_Op<"address_of_return_address"> { Examples: ```mlir - %addr = address_of_return_address() : !cir.ptr<!cir.int<u, 8>> + %addr = address_of_return_address() : !cir.ptr<!u8i> ``` }]; diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index b4f02c97f539a..b737c9e618d62 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -869,20 +869,26 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl &gd, unsigned builtinID, break; // Handled as library calls below. case Builtin::BI__builtin_dwarf_cfa: return errorBuiltinNYI(*this, e, builtinID); - case Builtin::BI__builtin_return_address: - case Builtin::BI_ReturnAddress: - case Builtin::BI__builtin_frame_address: { - mlir::Location loc = getLoc(e->getExprLoc()); + case Builtin::BI__builtin_return_address: { llvm::APSInt level = e->getArg(0)->EvaluateKnownConstInt(getContext()); - if (builtinID == Builtin::BI__builtin_return_address) { - return RValue::get(cir::ReturnAddrOp::create( - builder, loc, - builder.getConstAPInt(loc, builder.getUInt32Ty(), level))); - } - return RValue::get(cir::FrameAddrOp::create( - builder, loc, + return RValue::get(cir::ReturnAddrOp::create( + builder, getLoc(e->getExprLoc()), builder.getConstAPInt(loc, builder.getUInt32Ty(), level))); } + case Builtin::BI_ReturnAddress: { + return RValue::get(cir::ReturnAddrOp::create( + builder, getLoc(e->getExprLoc()), + builder.getConstInt(loc, builder.getUInt32Ty(), 0))); + } + case Builtin::BI__builtin_frame_address: { + llvm::APSInt level = e->getArg(0)->EvaluateKnownConstInt(getContext()); + mlir::Location loc = getLoc(e->getExprLoc()); + mlir::Value addr = cir::FrameAddrOp::create( + builder, loc, allocaInt8PtrTy, + builder.getConstAPInt(loc, builder.getUInt32Ty(), level)); + return RValue::get( + builder.createCast(loc, cir::CastKind::bitcast, addr, voidPtrTy)); + } case Builtin::BI__builtin_extract_return_addr: case Builtin::BI__builtin_frob_return_addr: case Builtin::BI__builtin_dwarf_sp_column: diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 73f9e5390b886..22c6e87f53311 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -1638,7 +1638,7 @@ mlir::LogicalResult CIRToLLVMCallOpLowering::matchAndRewrite( mlir::LogicalResult CIRToLLVMReturnAddrOpLowering::matchAndRewrite( cir::ReturnAddrOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { - auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext()); + const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType()); replaceOpWithCallLLVMIntrinsicOp(rewriter, op, "llvm.returnaddress", llvmPtrTy, adaptor.getOperands()); return mlir::success(); @@ -1647,7 +1647,7 @@ mlir::LogicalResult CIRToLLVMReturnAddrOpLowering::matchAndRewrite( mlir::LogicalResult CIRToLLVMFrameAddrOpLowering::matchAndRewrite( cir::FrameAddrOp op, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { - auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext()); + const mlir::Type llvmPtrTy = getTypeConverter()->convertType(op.getType()); replaceOpWithCallLLVMIntrinsicOp(rewriter, op, "llvm.frameaddress", llvmPtrTy, adaptor.getOperands()); return mlir::success(); diff --git a/clang/test/CIR/CodeGen/ms-intrinsics.c b/clang/test/CIR/CodeGen/ms-intrinsics.c index fa6872c207c92..61c867a946743 100644 --- a/clang/test/CIR/CodeGen/ms-intrinsics.c +++ b/clang/test/CIR/CodeGen/ms-intrinsics.c @@ -23,9 +23,24 @@ // CIR shall be able to support fully. void *_AddressOfReturnAddress(void); +void *_ReturnAddress(void); + +void *test_ReturnAddress(void) { + return _ReturnAddress(); + // CIR-LABEL: test_ReturnAddress + // CIR: [[ARG:%.*]] = cir.const #cir.int<0> : !u32i + // CIR: {{%.*}} = cir.return_address([[ARG]]) + + // LLVM-LABEL: test_ReturnAddress + // LLVM: {{%.*}} = call ptr @llvm.returnaddress(i32 0) + + // OGCG-LABEL: test_ReturnAddress + // OGCG: {{%.*}} = call ptr @llvm.returnaddress(i32 0) +} #if defined(__i386__) || defined(__x86_64__) || defined (__aarch64__) void *test_AddressOfReturnAddress(void) { + return _AddressOfReturnAddress(); // CIR-LABEL: test_AddressOfReturnAddress // CIR: %[[ADDR:.*]] = cir.address_of_return_address : !cir.ptr<!u8i> // CIR: %{{.*}} = cir.cast bitcast %[[ADDR]] : !cir.ptr<!u8i> -> !cir.ptr<!void> @@ -35,6 +50,5 @@ void *test_AddressOfReturnAddress(void) { // OGCG-LABEL: test_AddressOfReturnAddress // OGCG: call ptr @llvm.addressofreturnaddress.p0() - return _AddressOfReturnAddress(); } #endif diff --git a/clang/test/CIR/CodeGenBuiltins/builtins.cpp b/clang/test/CIR/CodeGenBuiltins/builtins.cpp index 0e434809fe6be..1c28c94a20413 100644 --- a/clang/test/CIR/CodeGenBuiltins/builtins.cpp +++ b/clang/test/CIR/CodeGenBuiltins/builtins.cpp @@ -32,7 +32,8 @@ extern "C" void *test_frame_address(void) { // CIR-LABEL: test_frame_address // CIR: [[ARG:%.*]] = cir.const #cir.int<1> : !u32i - // CIR: {{%.*}} = cir.frame_address([[ARG]]) + // CIR: %[[ADDR:.*]] = cir.frame_address([[ARG]]) : !cir.ptr<!u8i> + // CIR: {{%.*}} = cir.cast bitcast %[[ADDR]] : !cir.ptr<!u8i> -> !cir.ptr<!void> // LLVM-LABEL: @test_frame_address // LLVM: {{%.*}} = call ptr @llvm.frameaddress.p0(i32 1) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
