[clang] 6d6c0cc - [CIR][X86] Implement lowering for `_AddressOfReturnAddress` builtin (#171974)
via cfe-commits
cfe-commits at lists.llvm.org
Thu Dec 18 14:48:23 PST 2025
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)
More information about the cfe-commits
mailing list