Author: Haocong Lu Date: 2025-12-18T14:48:19-08:00 New Revision: 6d6c0cc3bb9123f0b915c0593ec3105a538e0d51
URL: https://github.com/llvm/llvm-project/commit/6d6c0cc3bb9123f0b915c0593ec3105a538e0d51 DIFF: https://github.com/llvm/llvm-project/commit/6d6c0cc3bb9123f0b915c0593ec3105a538e0d51.diff LOG: [CIR][X86] Implement lowering for `_AddressOfReturnAddress` builtin (#171974) - Add new `CIR_AddrOfReturnAddrOp` and support lowering it to LLVMIR - Add CIR CodeGen for `_AddressOfReturnAddress` X86 builtin - Fix error return type of `FrameAddrOp`, and add missing test for `_ReturnAddress` Part of https://github.com/llvm/llvm-project/issues/167765 Added: clang/test/CIR/CodeGen/ms-intrinsics.c Modified: clang/include/clang/CIR/Dialect/IR/CIROps.td clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp clang/test/CIR/CodeGenBuiltins/builtins.cpp Removed: ################################################################################ diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 630d357f40db7..7e7424fd71878 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -3313,15 +3313,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"; @@ -3338,12 +3330,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"; @@ -3366,9 +3362,36 @@ 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))"; +} + +//===----------------------------------------------------------------------===// +// 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<!u8i> ``` }]; + + let results = (outs CIR_PointerType:$result); + let assemblyFormat = "attr-dict `:` qualified(type($result))"; } //===----------------------------------------------------------------------===// 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/CodeGen/CIRGenBuiltinX86.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp index 5f2771fbd268c..bd373b1423fd0 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp @@ -1758,7 +1758,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 611850e7ae44b..6d01964ebac41 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -1628,7 +1628,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(); @@ -1637,12 +1637,21 @@ 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(); } +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..61c867a946743 --- /dev/null +++ b/clang/test/CIR/CodeGen/ms-intrinsics.c @@ -0,0 +1,54 @@ +// 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); +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> + + // LLVM-LABEL: test_AddressOfReturnAddress + // LLVM: call ptr @llvm.addressofreturnaddress.p0() + + // OGCG-LABEL: test_AddressOfReturnAddress + // OGCG: call ptr @llvm.addressofreturnaddress.p0() +} +#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
