Skip to content

Commit 81285c7

Browse files
ghehglanza
authored andcommitted
[CIR][CIRGen][Builtin] Support __builtin_frame_address (#1137)
1 parent c53b6c1 commit 81285c7

File tree

6 files changed

+80
-13
lines changed

6 files changed

+80
-13
lines changed

clang/include/clang/CIR/Dialect/IR/CIROps.td

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4227,13 +4227,21 @@ def MemChrOp : CIR_Op<"libc.memchr"> {
42274227
}
42284228

42294229
//===----------------------------------------------------------------------===//
4230-
// ReturnAddrOp
4230+
// ReturnAddrOp and FrameAddrOp
42314231
//===----------------------------------------------------------------------===//
42324232

4233-
def ReturnAddrOp : CIR_Op<"return_address"> {
4233+
class FuncAddrBuiltinOp<string mnemonic> : CIR_Op<mnemonic, []> {
42344234
let arguments = (ins UInt32:$level);
4235-
let summary = "The return address of the current function, or of one of its callers";
42364235
let results = (outs Res<VoidPtr, "">:$result);
4236+
let assemblyFormat = [{
4237+
`(` $level `)` attr-dict
4238+
}];
4239+
let hasVerifier = 0;
4240+
}
4241+
4242+
def ReturnAddrOp : FuncAddrBuiltinOp<"return_address"> {
4243+
let summary =
4244+
"The return address of the current function, or of one of its callers";
42374245

42384246
let description = [{
42394247
Represents call to builtin function ` __builtin_return_address` in CIR.
@@ -4250,11 +4258,34 @@ def ReturnAddrOp : CIR_Op<"return_address"> {
42504258
%p = return_address(%level) -> !cir.ptr<!void>
42514259
```
42524260
}];
4261+
}
42534262

4254-
let assemblyFormat = [{
4255-
`(` $level `)` attr-dict
4263+
def FrameAddrOp : FuncAddrBuiltinOp<"frame_address"> {
4264+
let summary =
4265+
"The frame address of the current function, or of one of its callers";
4266+
4267+
let description = [{
4268+
Represents call to builtin function ` __builtin_frame_address` in CIR.
4269+
This builtin function returns the frame address of the current function,
4270+
or of one of its callers. The frame is the area on the stack that holds
4271+
local variables and saved registers. The frame address is normally the
4272+
address of the first word pushed on to the stack by the function.
4273+
However, the exact definition depends upon the processor and the calling
4274+
convention. If the processor has a dedicated frame pointer register, and
4275+
the function has a frame, then __builtin_frame_address returns the value of
4276+
the frame pointer register.
4277+
4278+
The `level` argument is number of frames to scan up the call stack.
4279+
For instance, value of 0 yields the frame address of the current function,
4280+
value of 1 yields the frame address of the caller of the current function,
4281+
and so forth.
4282+
4283+
Examples:
4284+
4285+
```mlir
4286+
%p = frame_address(%level) -> !cir.ptr<!void>
4287+
```
42564288
}];
4257-
let hasVerifier = 0;
42584289
}
42594290

42604291
//===----------------------------------------------------------------------===//

clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1592,18 +1592,21 @@ RValue CIRGenFunction::emitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
15921592
llvm_unreachable("BI__builtin_wmemcmp NYI");
15931593
case Builtin::BI__builtin_dwarf_cfa:
15941594
llvm_unreachable("BI__builtin_dwarf_cfa NYI");
1595-
case Builtin::BI__builtin_return_address: {
1595+
case Builtin::BI__builtin_return_address:
1596+
case Builtin::BI__builtin_frame_address: {
15961597
mlir::Location loc = getLoc(E->getExprLoc());
15971598
mlir::Attribute levelAttr = ConstantEmitter(*this).emitAbstract(
15981599
E->getArg(0), E->getArg(0)->getType());
1599-
int64_t level = mlir::cast<cir::IntAttr>(levelAttr).getSInt();
1600+
uint64_t level = mlir::cast<cir::IntAttr>(levelAttr).getUInt();
1601+
if (BuiltinID == Builtin::BI__builtin_return_address) {
1602+
return RValue::get(builder.create<cir::ReturnAddrOp>(
1603+
loc, builder.getUInt32(level, loc)));
1604+
}
16001605
return RValue::get(
1601-
builder.create<cir::ReturnAddrOp>(loc, builder.getUInt32(level, loc)));
1606+
builder.create<cir::FrameAddrOp>(loc, builder.getUInt32(level, loc)));
16021607
}
16031608
case Builtin::BI_ReturnAddress:
16041609
llvm_unreachable("BI_ReturnAddress NYI");
1605-
case Builtin::BI__builtin_frame_address:
1606-
llvm_unreachable("BI__builtin_frame_address NYI");
16071610
case Builtin::BI__builtin_extract_return_addr:
16081611
llvm_unreachable("BI__builtin_extract_return_addr NYI");
16091612
case Builtin::BI__builtin_frob_return_addr:

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3612,6 +3612,15 @@ mlir::LogicalResult CIRToLLVMReturnAddrOpLowering::matchAndRewrite(
36123612
return mlir::success();
36133613
}
36143614

3615+
mlir::LogicalResult CIRToLLVMFrameAddrOpLowering::matchAndRewrite(
3616+
cir::FrameAddrOp op, OpAdaptor adaptor,
3617+
mlir::ConversionPatternRewriter &rewriter) const {
3618+
auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
3619+
replaceOpWithCallLLVMIntrinsicOp(rewriter, op, "llvm.frameaddress", llvmPtrTy,
3620+
adaptor.getOperands());
3621+
return mlir::success();
3622+
}
3623+
36153624
mlir::LogicalResult CIRToLLVMClearCacheOpLowering::matchAndRewrite(
36163625
cir::ClearCacheOp op, OpAdaptor adaptor,
36173626
mlir::ConversionPatternRewriter &rewriter) const {
@@ -3888,6 +3897,7 @@ void populateCIRToLLVMConversionPatterns(
38883897
CIRToLLVMEhInflightOpLowering,
38893898
CIRToLLVMEhTypeIdOpLowering,
38903899
CIRToLLVMExpectOpLowering,
3900+
CIRToLLVMFrameAddrOpLowering,
38913901
CIRToLLVMFreeExceptionOpLowering,
38923902
CIRToLLVMFuncOpLowering,
38933903
CIRToLLVMGetBitfieldOpLowering,

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -936,6 +936,16 @@ class CIRToLLVMReturnAddrOpLowering
936936
mlir::ConversionPatternRewriter &) const override;
937937
};
938938

939+
class CIRToLLVMFrameAddrOpLowering
940+
: public mlir::OpConversionPattern<cir::FrameAddrOp> {
941+
public:
942+
using mlir::OpConversionPattern<cir::FrameAddrOp>::OpConversionPattern;
943+
944+
mlir::LogicalResult
945+
matchAndRewrite(cir::FrameAddrOp op, OpAdaptor,
946+
mlir::ConversionPatternRewriter &) const override;
947+
};
948+
939949
class CIRToLLVMClearCacheOpLowering
940950
: public mlir::OpConversionPattern<cir::ClearCacheOp> {
941951
public:

clang/test/CIR/CodeGen/builtins.cpp

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,9 +100,20 @@ extern "C" void *test_return_address(void) {
100100
return __builtin_return_address(1);
101101

102102
// CIR-LABEL: test_return_address
103-
// [[ARG:%.*]] = cir.const #cir.int<1> : !u32i
104-
// {{%.*}} = cir.return_address([[ARG]])
103+
// CIR: [[ARG:%.*]] = cir.const #cir.int<1> : !u32i
104+
// CIR: {{%.*}} = cir.return_address([[ARG]])
105105

106106
// LLVM-LABEL: @test_return_address
107107
// LLVM: {{%.*}} = call ptr @llvm.returnaddress(i32 1)
108108
}
109+
110+
extern "C" void *test_frame_address(void) {
111+
return __builtin_frame_address(1);
112+
113+
// CIR-LABEL: test_frame_address
114+
// CIR: [[ARG:%.*]] = cir.const #cir.int<1> : !u32i
115+
// CIR: {{%.*}} = cir.frame_address([[ARG]])
116+
117+
// LLVM-LABEL: @test_frame_address
118+
// LLVM: {{%.*}} = call ptr @llvm.frameaddress.p0(i32 1)
119+
}

clang/test/CIR/IR/builtins.cir

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ module {
55
cir.func @test1() {
66
%0 = cir.const #cir.int<1> : !u32i
77
%1 = cir.return_address(%0)
8+
%2 = cir.frame_address(%0)
89
cir.return
910
}
1011
// CHECK: cir.func @test1()
1112
// CHECK: %0 = cir.const #cir.int<1> : !u32i
1213
// CHECK: %1 = cir.return_address(%0)
14+
// CHECK: %2 = cir.frame_address(%0)
1315
// CHECK: cir.return
1416
}

0 commit comments

Comments
 (0)