llvm.org GIT mirror llvm / dfab481
[XRay] Support for for tail calls for ARM no-Thumb This patch adds simplified support for tail calls on ARM with XRay instrumentation. Known issue: compiled with generic flags: `-O3 -g -fxray-instrument -Wall -std=c++14 -ffunction-sections -fdata-sections` (this list doesn't include my specific flags like --target=armv7-linux-gnueabihf etc.), the following program #include <cstdio> #include <cassert> #include <xray/xray_interface.h> [[clang::xray_always_instrument]] void __attribute__ ((noinline)) fC() { std::printf("In fC()\n"); } [[clang::xray_always_instrument]] void __attribute__ ((noinline)) fB() { std::printf("In fB()\n"); fC(); } [[clang::xray_always_instrument]] void __attribute__ ((noinline)) fA() { std::printf("In fA()\n"); fB(); } // Avoid infinite recursion in case the logging function is instrumented (so calls logging // function again). [[clang::xray_never_instrument]] void simplyPrint(int32_t functionId, XRayEntryType xret) { printf("XRay: functionId=%d type=%d.\n", int(functionId), int(xret)); } int main(int argc, char* argv[]) { __xray_set_handler(simplyPrint); printf("Patching...\n"); __xray_patch(); fA(); printf("Unpatching...\n"); __xray_unpatch(); fA(); return 0; } gives the following output: Patching... XRay: functionId=3 type=0. In fA() XRay: functionId=3 type=1. XRay: functionId=2 type=0. In fB() XRay: functionId=2 type=1. XRay: functionId=1 type=0. XRay: functionId=1 type=1. In fC() Unpatching... In fA() In fB() In fC() So for function fC() the exit sled seems to be called too much before function exit: before printing In fC(). Debugging shows that the above happens because printf from fC is also called as a tail call. So first the exit sled of fC is executed, and only then printf is jumped into. So it seems we can't do anything about this with the current approach (i.e. within the simplification described in https://reviews.llvm.org/D23988 ). Differential Revision: https://reviews.llvm.org/D25030 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@284456 91177308-0d34-0410-b5e6-96231b3b80d8 Dean Michael Berris 3 years ago
5 changed file(s) with 72 addition(s) and 3 deletion(s). Raw diff Collapse all Expand all
9494 {
9595 for (auto &MBB : MF) {
9696 for (auto &T : MBB.terminators()) {
97 unsigned Opc = 0;
9798 if (T.isReturn()) {
98 // Prepend the return instruction with PATCHABLE_FUNCTION_EXIT
99 BuildMI(MBB, T, T.getDebugLoc(),
100 TII->get(TargetOpcode::PATCHABLE_FUNCTION_EXIT));
99 Opc = TargetOpcode::PATCHABLE_FUNCTION_EXIT;
100 }
101 if (TII->isTailCall(T)) {
102 Opc = TargetOpcode::PATCHABLE_TAIL_CALL;
103 }
104 if (Opc != 0) {
105 // Prepend the return instruction with PATCHABLE_FUNCTION_EXIT or
106 // PATCHABLE_TAIL_CALL .
107 BuildMI(MBB, T, T.getDebugLoc(),TII->get(Opc));
101108 }
102109 }
103110 }
20492049 case ARM::PATCHABLE_FUNCTION_EXIT:
20502050 LowerPATCHABLE_FUNCTION_EXIT(*MI);
20512051 return;
2052 case ARM::PATCHABLE_TAIL_CALL:
2053 LowerPATCHABLE_TAIL_CALL(*MI);
2054 return;
20522055 }
20532056
20542057 MCInst TmpInst;
111111 // XRay-specific lowering for ARM.
112112 void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI);
113113 void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI);
114 void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI);
114115 // Helper function that emits the XRay sleds we've collected for a particular
115116 // function.
116117 void EmitXRayTable();
218218 EmitSled(MI, SledKind::FUNCTION_EXIT);
219219 }
220220
221 void ARMAsmPrinter::LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI)
222 {
223 EmitSled(MI, SledKind::TAIL_CALL);
224 }
225
221226 void ARMAsmPrinter::EmitXRayTable()
222227 {
223228 if (Sleds.empty())
0 ; RUN: llc -filetype=asm -o - -mtriple=armv7-unknown-linux-gnu < %s | FileCheck %s
1
2 define i32 @callee() nounwind noinline uwtable "function-instrument"="xray-always" {
3 ; CHECK: .p2align 2
4 ; CHECK-LABEL: Lxray_sled_0:
5 ; CHECK-NEXT: b #20
6 ; CHECK-NEXT: nop
7 ; CHECK-NEXT: nop
8 ; CHECK-NEXT: nop
9 ; CHECK-NEXT: nop
10 ; CHECK-NEXT: nop
11 ; CHECK-NEXT: nop
12 ; CHECK-LABEL: Ltmp0:
13 ret i32 0
14 ; CHECK-NEXT: mov r0, #0
15 ; CHECK-NEXT: .p2align 2
16 ; CHECK-LABEL: Lxray_sled_1:
17 ; CHECK-NEXT: b #20
18 ; CHECK-NEXT: nop
19 ; CHECK-NEXT: nop
20 ; CHECK-NEXT: nop
21 ; CHECK-NEXT: nop
22 ; CHECK-NEXT: nop
23 ; CHECK-NEXT: nop
24 ; CHECK-LABEL: Ltmp1:
25 ; CHECK-NEXT: bx lr
26 }
27
28 define i32 @caller() nounwind noinline uwtable "function-instrument"="xray-always" {
29 ; CHECK: .p2align 2
30 ; CHECK-LABEL: Lxray_sled_2:
31 ; CHECK-NEXT: b #20
32 ; CHECK-NEXT: nop
33 ; CHECK-NEXT: nop
34 ; CHECK-NEXT: nop
35 ; CHECK-NEXT: nop
36 ; CHECK-NEXT: nop
37 ; CHECK-NEXT: nop
38 ; CHECK-LABEL: Ltmp2:
39 ; CHECK: .p2align 2
40 ; CHECK-LABEL: Lxray_sled_3:
41 ; CHECK-NEXT: b #20
42 ; CHECK-NEXT: nop
43 ; CHECK-NEXT: nop
44 ; CHECK-NEXT: nop
45 ; CHECK-NEXT: nop
46 ; CHECK-NEXT: nop
47 ; CHECK-NEXT: nop
48 ; CHECK-LABEL: Ltmp3:
49 %retval = tail call i32 @callee()
50 ; CHECK: b callee
51 ret i32 %retval
52 }