Skip to content

Commit eafbab6

Browse files
authored
[EntryExitInstrumenter][AArch64][RISCV][LoongArch] Pass __builtin_return_address(0) into _mcount (#121107)
On RISC-V, AArch64, and LoongArch, the `_mcount` function takes `__builtin_return_address(0)` as an argument since `__builtin_return_address(1)` is not available on these platforms. This patch fixes the argument passing to match the behavior of glibc/gcc. Closes #121103.
1 parent 2838066 commit eafbab6

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,21 @@ static void insertCall(Function &CurFn, StringRef Func,
4848
/*isVarArg=*/false)),
4949
{GV}, "", InsertionPt);
5050
Call->setDebugLoc(DL);
51+
} else if (TargetTriple.isRISCV() || TargetTriple.isAArch64() ||
52+
TargetTriple.isLoongArch()) {
53+
// On RISC-V, AArch64, and LoongArch, the `_mcount` function takes
54+
// `__builtin_return_address(0)` as an argument since
55+
// `__builtin_return_address(1)` is not available on these platforms.
56+
Instruction *RetAddr = CallInst::Create(
57+
Intrinsic::getOrInsertDeclaration(&M, Intrinsic::returnaddress),
58+
ConstantInt::get(Type::getInt32Ty(C), 0), "", InsertionPt);
59+
RetAddr->setDebugLoc(DL);
60+
61+
FunctionCallee Fn = M.getOrInsertFunction(
62+
Func, FunctionType::get(Type::getVoidTy(C), PointerType::getUnqual(C),
63+
false));
64+
CallInst *Call = CallInst::Create(Fn, RetAddr, "", InsertionPt);
65+
Call->setDebugLoc(DL);
5166
} else {
5267
FunctionCallee Fn = M.getOrInsertFunction(Func, Type::getVoidTy(C));
5368
CallInst *Call = CallInst::Create(Fn, "", InsertionPt);
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -mtriple=riscv64 -passes="ee-instrument<post-inline>" -S < %s | FileCheck %s --check-prefixes=CHECK,RISCV64
3+
; RUN: opt -mtriple=riscv32 -passes="ee-instrument<post-inline>" -S < %s | FileCheck %s --check-prefixes=CHECK,RISCV32
4+
; RUN: opt -mtriple=loongarch64 -passes="ee-instrument<post-inline>" -S < %s | FileCheck %s --check-prefixes=CHECK,LOONGARCH64
5+
; RUN: opt -mtriple=loongarch32 -passes="ee-instrument<post-inline>" -S < %s | FileCheck %s --check-prefixes=CHECK,LOONGARCH32
6+
; RUN: opt -mtriple=aarch64 -passes="ee-instrument<post-inline>" -S < %s | FileCheck %s --check-prefixes=CHECK,AARCH64
7+
; RUN: opt -mtriple=aarch64_be -passes="ee-instrument<post-inline>" -S < %s | FileCheck %s --check-prefixes=CHECK,AARCH64_BE
8+
; RUN: opt -mtriple=aarch64_32 -passes="ee-instrument<post-inline>" -S < %s | FileCheck %s --check-prefixes=CHECK,AARCH64_32
9+
10+
define void @f1() "instrument-function-entry-inlined"="_mcount" {
11+
; CHECK-LABEL: define void @f1() {
12+
; CHECK-NEXT: [[TMP1:%.*]] = call ptr @llvm.returnaddress(i32 0)
13+
; CHECK-NEXT: call void @_mcount(ptr [[TMP1]])
14+
; CHECK-NEXT: ret void
15+
;
16+
ret void
17+
}
18+
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
19+
; AARCH64: {{.*}}
20+
; AARCH64_32: {{.*}}
21+
; AARCH64_BE: {{.*}}
22+
; LOONGARCH32: {{.*}}
23+
; LOONGARCH64: {{.*}}
24+
; RISCV32: {{.*}}
25+
; RISCV64: {{.*}}

0 commit comments

Comments
 (0)