Skip to content

Commit f858c4e

Browse files
authored
[CIR][CIRGen][Builtin] Support __builtin_return_address (#1046)
test case is from [Traditional Clang CodeGen test file](https://github.com/llvm/clangir/blob/723e78afb5ae4fbd000269a057410913ade3ef44/clang/test/CodeGen/2004-02-13-BuiltinFrameReturnAddress.c#L5)
1 parent edc337b commit f858c4e

File tree

5 files changed

+88
-4
lines changed

5 files changed

+88
-4
lines changed

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

+31
Original file line numberDiff line numberDiff line change
@@ -4125,6 +4125,37 @@ def MemChrOp : CIR_Op<"libc.memchr"> {
41254125
let hasVerifier = 0;
41264126
}
41274127

4128+
//===----------------------------------------------------------------------===//
4129+
// ReturnAddrOp
4130+
//===----------------------------------------------------------------------===//
4131+
4132+
def ReturnAddrOp : CIR_Op<"return_address"> {
4133+
let arguments = (ins UInt32:$level);
4134+
let summary = "The return address of the current function, or of one of its callers";
4135+
let results = (outs Res<VoidPtr, "">:$result);
4136+
4137+
let description = [{
4138+
Represents call to builtin function ` __builtin_return_address` in CIR.
4139+
This builtin function returns the return address of the current function,
4140+
or of one of its callers.
4141+
The `level` argument is number of frames to scan up the call stack.
4142+
For instance, value of 0 yields the return address of the current function,
4143+
value of 1 yields the return address of the caller of the current function,
4144+
and so forth.
4145+
4146+
Examples:
4147+
4148+
```mlir
4149+
%p = return_address(%level) -> !cir.ptr<!void>
4150+
```
4151+
}];
4152+
4153+
let assemblyFormat = [{
4154+
`(` $level `)` attr-dict
4155+
}];
4156+
let hasVerifier = 0;
4157+
}
4158+
41284159
//===----------------------------------------------------------------------===//
41294160
// StdFindOp
41304161
//===----------------------------------------------------------------------===//

clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp

+8-2
Original file line numberDiff line numberDiff line change
@@ -1510,8 +1510,14 @@ RValue CIRGenFunction::buildBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
15101510
llvm_unreachable("BI__builtin_wmemcmp NYI");
15111511
case Builtin::BI__builtin_dwarf_cfa:
15121512
llvm_unreachable("BI__builtin_dwarf_cfa NYI");
1513-
case Builtin::BI__builtin_return_address:
1514-
llvm_unreachable("BI__builtin_return_address NYI");
1513+
case Builtin::BI__builtin_return_address: {
1514+
mlir::Location loc = getLoc(E->getExprLoc());
1515+
mlir::Attribute levelAttr = ConstantEmitter(*this).emitAbstract(
1516+
E->getArg(0), E->getArg(0)->getType());
1517+
int64_t level = mlir::cast<mlir::cir::IntAttr>(levelAttr).getSInt();
1518+
return RValue::get(builder.create<mlir::cir::ReturnAddrOp>(
1519+
loc, builder.getUInt32(level, loc)));
1520+
}
15151521
case Builtin::BI_ReturnAddress:
15161522
llvm_unreachable("BI_ReturnAddress NYI");
15171523
case Builtin::BI__builtin_frame_address:

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

+24-2
Original file line numberDiff line numberDiff line change
@@ -4115,6 +4115,21 @@ class CIRCmpThreeWayOpLowering
41154115
}
41164116
};
41174117

4118+
class CIRReturnAddrOpLowering
4119+
: public mlir::OpConversionPattern<mlir::cir::ReturnAddrOp> {
4120+
public:
4121+
using OpConversionPattern<mlir::cir::ReturnAddrOp>::OpConversionPattern;
4122+
4123+
mlir::LogicalResult
4124+
matchAndRewrite(mlir::cir::ReturnAddrOp op, OpAdaptor adaptor,
4125+
mlir::ConversionPatternRewriter &rewriter) const override {
4126+
auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4127+
replaceOpWithCallLLVMIntrinsicOp(rewriter, op, "llvm.returnaddress",
4128+
llvmPtrTy, adaptor.getOperands());
4129+
return mlir::success();
4130+
}
4131+
};
4132+
41184133
class CIRClearCacheOpLowering
41194134
: public mlir::OpConversionPattern<mlir::cir::ClearCacheOp> {
41204135
public:
@@ -4370,9 +4385,16 @@ void populateCIRToLLVMConversionPatterns(
43704385
CIRVectorShuffleVecLowering, CIRStackSaveLowering, CIRUnreachableLowering,
43714386
CIRTrapLowering, CIRInlineAsmOpLowering, CIRSetBitfieldLowering,
43724387
CIRGetBitfieldLowering, CIRPrefetchLowering, CIRObjSizeOpLowering,
4388+
CIRIsConstantOpLowering, CIRCmpThreeWayOpLowering, CIRMemCpyOpLowering,
4389+
CIRFAbsOpLowering, CIRExpectOpLowering, CIRVTableAddrPointOpLowering,
4390+
CIRVectorCreateLowering, CIRVectorCmpOpLowering, CIRVectorSplatLowering,
4391+
CIRVectorTernaryLowering, CIRVectorShuffleIntsLowering,
4392+
CIRVectorShuffleVecLowering, CIRStackSaveLowering, CIRUnreachableLowering,
4393+
CIRTrapLowering, CIRInlineAsmOpLowering, CIRSetBitfieldLowering,
4394+
CIRGetBitfieldLowering, CIRPrefetchLowering, CIRObjSizeOpLowering,
43734395
CIRIsConstantOpLowering, CIRCmpThreeWayOpLowering,
4374-
CIRClearCacheOpLowering, CIREhTypeIdOpLowering, CIRCatchParamOpLowering,
4375-
CIRResumeOpLowering, CIRAllocExceptionOpLowering,
4396+
CIRReturnAddrOpLowering, CIRClearCacheOpLowering, CIREhTypeIdOpLowering,
4397+
CIRCatchParamOpLowering, CIRResumeOpLowering, CIRAllocExceptionOpLowering,
43764398
CIRFreeExceptionOpLowering, CIRThrowOpLowering, CIRIntrinsicCallLowering,
43774399
CIRAssumeLowering, CIRAssumeAlignedLowering, CIRAssumeSepStorageLowering,
43784400
CIRBaseClassAddrOpLowering, CIRDerivedClassAddrOpLowering,

clang/test/CIR/CodeGen/builtins.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,14 @@ extern "C" char* test_memchr(const char arg[32]) {
7575
// LLVM: [[RET:%.*]] = load ptr, ptr [[RET_P]], align 8
7676
// LLVM: ret ptr [[RET]]
7777
}
78+
79+
extern "C" void *test_return_address(void) {
80+
return __builtin_return_address(1);
81+
82+
// CIR-LABEL: test_return_address
83+
// [[ARG:%.*]] = cir.const #cir.int<1> : !u32i
84+
// {{%.*}} = cir.return_address([[ARG]])
85+
86+
// LLVM-LABEL: @test_return_address
87+
// LLVM: {{%.*}} = call ptr @llvm.returnaddress(i32 1)
88+
}

clang/test/CIR/IR/builtins.cir

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: cir-opt %s | cir-opt | FileCheck %s
2+
!u32i = !cir.int<u, 32>
3+
4+
module {
5+
cir.func @test1() {
6+
%0 = cir.const #cir.int<1> : !u32i
7+
%1 = cir.return_address(%0)
8+
cir.return
9+
}
10+
// CHECK: cir.func @test1()
11+
// CHECK: %0 = cir.const #cir.int<1> : !u32i
12+
// CHECK: %1 = cir.return_address(%0)
13+
// CHECK: cir.return
14+
}

0 commit comments

Comments
 (0)