[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 https://github.com/llvm/llvm-project/issues/121103.
This commit is contained in:
Yingwei Zheng 2025-01-01 15:02:08 +08:00 committed by GitHub
parent 283806695a
commit eafbab6fac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 40 additions and 0 deletions

View File

@ -48,6 +48,21 @@ static void insertCall(Function &CurFn, StringRef Func,
/*isVarArg=*/false)),
{GV}, "", InsertionPt);
Call->setDebugLoc(DL);
} else if (TargetTriple.isRISCV() || TargetTriple.isAArch64() ||
TargetTriple.isLoongArch()) {
// 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.
Instruction *RetAddr = CallInst::Create(
Intrinsic::getOrInsertDeclaration(&M, Intrinsic::returnaddress),
ConstantInt::get(Type::getInt32Ty(C), 0), "", InsertionPt);
RetAddr->setDebugLoc(DL);
FunctionCallee Fn = M.getOrInsertFunction(
Func, FunctionType::get(Type::getVoidTy(C), PointerType::getUnqual(C),
false));
CallInst *Call = CallInst::Create(Fn, RetAddr, "", InsertionPt);
Call->setDebugLoc(DL);
} else {
FunctionCallee Fn = M.getOrInsertFunction(Func, Type::getVoidTy(C));
CallInst *Call = CallInst::Create(Fn, "", InsertionPt);

View File

@ -0,0 +1,25 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
; RUN: opt -mtriple=riscv64 -passes="ee-instrument<post-inline>" -S < %s | FileCheck %s --check-prefixes=CHECK,RISCV64
; RUN: opt -mtriple=riscv32 -passes="ee-instrument<post-inline>" -S < %s | FileCheck %s --check-prefixes=CHECK,RISCV32
; RUN: opt -mtriple=loongarch64 -passes="ee-instrument<post-inline>" -S < %s | FileCheck %s --check-prefixes=CHECK,LOONGARCH64
; RUN: opt -mtriple=loongarch32 -passes="ee-instrument<post-inline>" -S < %s | FileCheck %s --check-prefixes=CHECK,LOONGARCH32
; RUN: opt -mtriple=aarch64 -passes="ee-instrument<post-inline>" -S < %s | FileCheck %s --check-prefixes=CHECK,AARCH64
; RUN: opt -mtriple=aarch64_be -passes="ee-instrument<post-inline>" -S < %s | FileCheck %s --check-prefixes=CHECK,AARCH64_BE
; RUN: opt -mtriple=aarch64_32 -passes="ee-instrument<post-inline>" -S < %s | FileCheck %s --check-prefixes=CHECK,AARCH64_32
define void @f1() "instrument-function-entry-inlined"="_mcount" {
; CHECK-LABEL: define void @f1() {
; CHECK-NEXT: [[TMP1:%.*]] = call ptr @llvm.returnaddress(i32 0)
; CHECK-NEXT: call void @_mcount(ptr [[TMP1]])
; CHECK-NEXT: ret void
;
ret void
}
;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
; AARCH64: {{.*}}
; AARCH64_32: {{.*}}
; AARCH64_BE: {{.*}}
; LOONGARCH32: {{.*}}
; LOONGARCH64: {{.*}}
; RISCV32: {{.*}}
; RISCV64: {{.*}}